/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

// THIS FILE IS GENERATED BY ZAP
#include "CHIPReadCallbacks.h"

#include <zap-generated/CHIPClientCallbacks.h>

#include <jni.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>
#include <platform/PlatformManager.h>

CHIPBooleanAttributeCallback::CHIPBooleanAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<BooleanAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBooleanAttributeCallback::~CHIPBooleanAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBooleanAttributeCallback::CallbackFn(void * context, bool value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBooleanAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBooleanAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Z)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jboolean>(value));
}

CHIPCharStringAttributeCallback::CHIPCharStringAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CharStringAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPCharStringAttributeCallback::~CHIPCharStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPCharStringAttributeCallback::CallbackFn(void * context, const chip::CharSpan value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPCharStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPCharStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;

    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/String;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));

    chip::UtfString valueStr(env, value);
    env->CallVoidMethod(javaCallbackRef, javaMethod, valueStr.jniValue());
}

CHIPDoubleAttributeCallback::CHIPDoubleAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<DoubleAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDoubleAttributeCallback::~CHIPDoubleAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDoubleAttributeCallback::CallbackFn(void * context, double value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDoubleAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDoubleAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(D)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jdouble>(value));
}

CHIPFloatAttributeCallback::CHIPFloatAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<FloatAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPFloatAttributeCallback::~CHIPFloatAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPFloatAttributeCallback::CallbackFn(void * context, float value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPFloatAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPFloatAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(F)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jfloat>(value));
}

CHIPInt8sAttributeCallback::CHIPInt8sAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int8sAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt8sAttributeCallback::~CHIPInt8sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt8sAttributeCallback::CallbackFn(void * context, int8_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt8sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt8sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(I)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jint>(value));
}

CHIPInt8uAttributeCallback::CHIPInt8uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int8uAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt8uAttributeCallback::~CHIPInt8uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt8uAttributeCallback::CallbackFn(void * context, uint8_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt8uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt8uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(I)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jint>(value));
}

CHIPInt16sAttributeCallback::CHIPInt16sAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int16sAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt16sAttributeCallback::~CHIPInt16sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt16sAttributeCallback::CallbackFn(void * context, int16_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt16sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt16sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(I)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jint>(value));
}

CHIPInt16uAttributeCallback::CHIPInt16uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int16uAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt16uAttributeCallback::~CHIPInt16uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt16uAttributeCallback::CallbackFn(void * context, uint16_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt16uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt16uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(I)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jint>(value));
}

CHIPInt32sAttributeCallback::CHIPInt32sAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int32sAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt32sAttributeCallback::~CHIPInt32sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt32sAttributeCallback::CallbackFn(void * context, int32_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt32sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt32sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(J)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jlong>(value));
}

CHIPInt32uAttributeCallback::CHIPInt32uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int32uAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt32uAttributeCallback::~CHIPInt32uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt32uAttributeCallback::CallbackFn(void * context, uint32_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt32uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt32uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(J)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jlong>(value));
}

CHIPInt64sAttributeCallback::CHIPInt64sAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int64sAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt64sAttributeCallback::~CHIPInt64sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt64sAttributeCallback::CallbackFn(void * context, int64_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt64sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt64sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(J)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jlong>(value));
}

CHIPInt64uAttributeCallback::CHIPInt64uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<Int64uAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPInt64uAttributeCallback::~CHIPInt64uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPInt64uAttributeCallback::CallbackFn(void * context, uint64_t value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPInt64uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPInt64uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(J)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));
    env->CallVoidMethod(javaCallbackRef, javaMethod, static_cast<jlong>(value));
}

CHIPOctetStringAttributeCallback::CHIPOctetStringAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<OctetStringAttributeCallback>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }
    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOctetStringAttributeCallback::~CHIPOctetStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOctetStringAttributeCallback::CallbackFn(void * context, const chip::ByteSpan value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOctetStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOctetStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    jobject javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogDetail(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;

    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "([B)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess method"));

    jbyteArray valueArr = env->NewByteArray(value.size());
    env->ExceptionClear();
    env->SetByteArrayRegion(valueArr, 0, value.size(), reinterpret_cast<const jbyte *>(value.data()));

    env->CallVoidMethod(javaCallbackRef, javaMethod, valueArr);
}

CHIPAccessControlAclAttributeCallback::CHIPAccessControlAclAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPAccessControlClusterAclAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAccessControlAclAttributeCallback::~CHIPAccessControlAclAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAccessControlAclAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::AccessControl::Structs::AccessControlEntry::DecodableType> &
        list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAccessControlAclAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAccessControlAclAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$AccessControlCluster$AclAttribute", attributeClass);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$AccessControlCluster$AclAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find AclAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        chip::FabricIndex fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool privilegeNull     = false;
        bool privilegeHasValue = true;

        chip::app::Clusters::AccessControl::Privilege privilegeValue = entry.privilege;

        jobject privilege = nullptr;
        if (!privilegeNull && privilegeHasValue)
        {
            jclass privilegeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", privilegeEntryCls);
            chip::JniClass privilegeJniClass(privilegeEntryCls);
            jmethodID privilegeEntryTypeCtor = env->GetMethodID(privilegeEntryCls, "<init>", "(I)V");
            privilege                        = env->NewObject(privilegeEntryCls, privilegeEntryTypeCtor, privilegeValue);
        }

        bool authModeNull     = false;
        bool authModeHasValue = true;

        chip::app::Clusters::AccessControl::AuthMode authModeValue = entry.authMode;

        jobject authMode = nullptr;
        if (!authModeNull && authModeHasValue)
        {
            jclass authModeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", authModeEntryCls);
            chip::JniClass authModeJniClass(authModeEntryCls);
            jmethodID authModeEntryTypeCtor = env->GetMethodID(authModeEntryCls, "<init>", "(I)V");
            authMode                        = env->NewObject(authModeEntryCls, authModeEntryTypeCtor, authModeValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, privilege, authMode);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create AclAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding AclAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAccessControlExtensionAttributeCallback::CHIPAccessControlExtensionAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPAccessControlClusterExtensionAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAccessControlExtensionAttributeCallback::~CHIPAccessControlExtensionAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAccessControlExtensionAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::AccessControl::Structs::ExtensionEntry::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAccessControlExtensionAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAccessControlExtensionAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$AccessControlCluster$ExtensionAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$AccessControlCluster$ExtensionAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;[B)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find ExtensionAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        chip::FabricIndex fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool dataNull     = false;
        bool dataHasValue = true;

        chip::ByteSpan dataValue = entry.data;

        jbyteArray data = nullptr;
        if (!dataNull && dataHasValue)
        {
            data = env->NewByteArray(dataValue.size());
            env->SetByteArrayRegion(data, 0, dataValue.size(), reinterpret_cast<const jbyte *>(dataValue.data()));
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, data);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create ExtensionAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ExtensionAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAccessControlAttributeListAttributeCallback::CHIPAccessControlAttributeListAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPAccessControlClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAccessControlAttributeListAttributeCallback::~CHIPAccessControlAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAccessControlAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAccessControlAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAccessControlAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAccountLoginAttributeListAttributeCallback::CHIPAccountLoginAttributeListAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPAccountLoginClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAccountLoginAttributeListAttributeCallback::~CHIPAccountLoginAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAccountLoginAttributeListAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAccountLoginAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAccountLoginAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback::CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPAdministratorCommissioningClusterAdminFabricIndexAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback::~CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback::CallbackFn(void * context, chip::FabricIndex value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAdministratorCommissioningAdminFabricIndexAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::FabricIndex>(javaValueClassName.c_str(),
                                                                            javaValueCtorSignature.c_str(), value, javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPAdministratorCommissioningAttributeListAttributeCallback::CHIPAdministratorCommissioningAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPAdministratorCommissioningClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAdministratorCommissioningAttributeListAttributeCallback::~CHIPAdministratorCommissioningAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAdministratorCommissioningAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAdministratorCommissioningAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAdministratorCommissioningAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPApplicationBasicAllowedVendorListAttributeCallback::CHIPApplicationBasicAllowedVendorListAttributeCallback(jobject javaCallback,
                                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPApplicationBasicClusterAllowedVendorListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPApplicationBasicAllowedVendorListAttributeCallback::~CHIPApplicationBasicAllowedVendorListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPApplicationBasicAllowedVendorListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::VendorId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPApplicationBasicAllowedVendorListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPApplicationBasicAllowedVendorListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry              = iter.GetValue();
        bool entryNull            = false;
        chip::VendorId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AllowedVendorListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPApplicationBasicAttributeListAttributeCallback::CHIPApplicationBasicAttributeListAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPApplicationBasicClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPApplicationBasicAttributeListAttributeCallback::~CHIPApplicationBasicAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPApplicationBasicAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPApplicationBasicAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPApplicationBasicAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPApplicationLauncherApplicationLauncherListAttributeCallback::CHIPApplicationLauncherApplicationLauncherListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPApplicationLauncherClusterApplicationLauncherListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPApplicationLauncherApplicationLauncherListAttributeCallback::~CHIPApplicationLauncherApplicationLauncherListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPApplicationLauncherApplicationLauncherListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<uint16_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPApplicationLauncherApplicationLauncherListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPApplicationLauncherApplicationLauncherListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry        = iter.GetValue();
        bool entryNull      = false;
        uint16_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ApplicationLauncherListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPApplicationLauncherAttributeListAttributeCallback::CHIPApplicationLauncherAttributeListAttributeCallback(jobject javaCallback,
                                                                                                             bool keepAlive) :
    chip::Callback::Callback<CHIPApplicationLauncherClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPApplicationLauncherAttributeListAttributeCallback::~CHIPApplicationLauncherAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPApplicationLauncherAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPApplicationLauncherAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPApplicationLauncherAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAudioOutputAudioOutputListAttributeCallback::CHIPAudioOutputAudioOutputListAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPAudioOutputClusterAudioOutputListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAudioOutputAudioOutputListAttributeCallback::~CHIPAudioOutputAudioOutputListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAudioOutputAudioOutputListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::AudioOutput::Structs::OutputInfo::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAudioOutputAudioOutputListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAudioOutputAudioOutputListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$AudioOutputCluster$AudioOutputListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$AudioOutputCluster$AudioOutputListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find AudioOutputListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool indexNull     = false;
        bool indexHasValue = true;

        uint8_t indexValue = entry.index;

        jobject index = nullptr;
        if (!indexNull && indexHasValue)
        {
            jclass indexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", indexEntryCls);
            chip::JniClass indexJniClass(indexEntryCls);
            jmethodID indexEntryTypeCtor = env->GetMethodID(indexEntryCls, "<init>", "(I)V");
            index                        = env->NewObject(indexEntryCls, indexEntryTypeCtor, indexValue);
        }

        bool outputTypeNull     = false;
        bool outputTypeHasValue = true;

        chip::app::Clusters::AudioOutput::OutputTypeEnum outputTypeValue = entry.outputType;

        jobject outputType = nullptr;
        if (!outputTypeNull && outputTypeHasValue)
        {
            jclass outputTypeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", outputTypeEntryCls);
            chip::JniClass outputTypeJniClass(outputTypeEntryCls);
            jmethodID outputTypeEntryTypeCtor = env->GetMethodID(outputTypeEntryCls, "<init>", "(I)V");
            outputType                        = env->NewObject(outputTypeEntryCls, outputTypeEntryTypeCtor, outputTypeValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, index, outputType, name);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create AudioOutputListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AudioOutputListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPAudioOutputAttributeListAttributeCallback::CHIPAudioOutputAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPAudioOutputClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPAudioOutputAttributeListAttributeCallback::~CHIPAudioOutputAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPAudioOutputAttributeListAttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPAudioOutputAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPAudioOutputAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBarrierControlAttributeListAttributeCallback::CHIPBarrierControlAttributeListAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPBarrierControlClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBarrierControlAttributeListAttributeCallback::~CHIPBarrierControlAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBarrierControlAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBarrierControlAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBarrierControlAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBasicAttributeListAttributeCallback::CHIPBasicAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPBasicClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBasicAttributeListAttributeCallback::~CHIPBasicAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBasicAttributeListAttributeCallback::CallbackFn(void * context,
                                                         const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBasicAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBasicAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBinaryInputBasicAttributeListAttributeCallback::CHIPBinaryInputBasicAttributeListAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPBinaryInputBasicClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBinaryInputBasicAttributeListAttributeCallback::~CHIPBinaryInputBasicAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBinaryInputBasicAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBinaryInputBasicAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBinaryInputBasicAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBindingAttributeListAttributeCallback::CHIPBindingAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPBindingClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBindingAttributeListAttributeCallback::~CHIPBindingAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBindingAttributeListAttributeCallback::CallbackFn(void * context,
                                                           const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBindingAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBindingAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBooleanStateAttributeListAttributeCallback::CHIPBooleanStateAttributeListAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPBooleanStateClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBooleanStateAttributeListAttributeCallback::~CHIPBooleanStateAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBooleanStateAttributeListAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBooleanStateAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBooleanStateAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBridgedActionsActionListAttributeCallback::CHIPBridgedActionsActionListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPBridgedActionsClusterActionListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBridgedActionsActionListAttributeCallback::~CHIPBridgedActionsActionListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBridgedActionsActionListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::BridgedActions::Structs::ActionStruct::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBridgedActionsActionListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBridgedActionsActionListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$BridgedActionsCluster$ActionListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$BridgedActionsCluster$ActionListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(
        attributeClass, "<init>",
        "(Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find ActionListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool actionIDNull     = false;
        bool actionIDHasValue = true;

        uint16_t actionIDValue = entry.actionID;

        jobject actionID = nullptr;
        if (!actionIDNull && actionIDHasValue)
        {
            jclass actionIDEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", actionIDEntryCls);
            chip::JniClass actionIDJniClass(actionIDEntryCls);
            jmethodID actionIDEntryTypeCtor = env->GetMethodID(actionIDEntryCls, "<init>", "(I)V");
            actionID                        = env->NewObject(actionIDEntryCls, actionIDEntryTypeCtor, actionIDValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool typeNull     = false;
        bool typeHasValue = true;

        chip::app::Clusters::BridgedActions::ActionTypeEnum typeValue = entry.type;

        jobject type = nullptr;
        if (!typeNull && typeHasValue)
        {
            jclass typeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", typeEntryCls);
            chip::JniClass typeJniClass(typeEntryCls);
            jmethodID typeEntryTypeCtor = env->GetMethodID(typeEntryCls, "<init>", "(I)V");
            type                        = env->NewObject(typeEntryCls, typeEntryTypeCtor, typeValue);
        }

        bool endpointListIDNull     = false;
        bool endpointListIDHasValue = true;

        uint16_t endpointListIDValue = entry.endpointListID;

        jobject endpointListID = nullptr;
        if (!endpointListIDNull && endpointListIDHasValue)
        {
            jclass endpointListIDEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", endpointListIDEntryCls);
            chip::JniClass endpointListIDJniClass(endpointListIDEntryCls);
            jmethodID endpointListIDEntryTypeCtor = env->GetMethodID(endpointListIDEntryCls, "<init>", "(I)V");
            endpointListID = env->NewObject(endpointListIDEntryCls, endpointListIDEntryTypeCtor, endpointListIDValue);
        }

        bool supportedCommandsNull     = false;
        bool supportedCommandsHasValue = true;

        uint16_t supportedCommandsValue = entry.supportedCommands;

        jobject supportedCommands = nullptr;
        if (!supportedCommandsNull && supportedCommandsHasValue)
        {
            jclass supportedCommandsEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", supportedCommandsEntryCls);
            chip::JniClass supportedCommandsJniClass(supportedCommandsEntryCls);
            jmethodID supportedCommandsEntryTypeCtor = env->GetMethodID(supportedCommandsEntryCls, "<init>", "(I)V");
            supportedCommands = env->NewObject(supportedCommandsEntryCls, supportedCommandsEntryTypeCtor, supportedCommandsValue);
        }

        bool statusNull     = false;
        bool statusHasValue = true;

        chip::app::Clusters::BridgedActions::ActionStateEnum statusValue = entry.status;

        jobject status = nullptr;
        if (!statusNull && statusHasValue)
        {
            jclass statusEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", statusEntryCls);
            chip::JniClass statusJniClass(statusEntryCls);
            jmethodID statusEntryTypeCtor = env->GetMethodID(statusEntryCls, "<init>", "(I)V");
            status                        = env->NewObject(statusEntryCls, statusEntryTypeCtor, statusValue);
        }

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, actionID, name, type, endpointListID, supportedCommands, status);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create ActionListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ActionListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBridgedActionsEndpointListAttributeCallback::CHIPBridgedActionsEndpointListAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPBridgedActionsClusterEndpointListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBridgedActionsEndpointListAttributeCallback::~CHIPBridgedActionsEndpointListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBridgedActionsEndpointListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::BridgedActions::Structs::EndpointListStruct::DecodableType> &
        list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBridgedActionsEndpointListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBridgedActionsEndpointListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$BridgedActionsCluster$EndpointListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$BridgedActionsCluster$EndpointListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find EndpointListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool endpointListIDNull     = false;
        bool endpointListIDHasValue = true;

        uint16_t endpointListIDValue = entry.endpointListID;

        jobject endpointListID = nullptr;
        if (!endpointListIDNull && endpointListIDHasValue)
        {
            jclass endpointListIDEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", endpointListIDEntryCls);
            chip::JniClass endpointListIDJniClass(endpointListIDEntryCls);
            jmethodID endpointListIDEntryTypeCtor = env->GetMethodID(endpointListIDEntryCls, "<init>", "(I)V");
            endpointListID = env->NewObject(endpointListIDEntryCls, endpointListIDEntryTypeCtor, endpointListIDValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool typeNull     = false;
        bool typeHasValue = true;

        chip::app::Clusters::BridgedActions::EndpointListTypeEnum typeValue = entry.type;

        jobject type = nullptr;
        if (!typeNull && typeHasValue)
        {
            jclass typeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", typeEntryCls);
            chip::JniClass typeJniClass(typeEntryCls);
            jmethodID typeEntryTypeCtor = env->GetMethodID(typeEntryCls, "<init>", "(I)V");
            type                        = env->NewObject(typeEntryCls, typeEntryTypeCtor, typeValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, endpointListID, name, type);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create EndpointListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding EndpointListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBridgedActionsAttributeListAttributeCallback::CHIPBridgedActionsAttributeListAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPBridgedActionsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBridgedActionsAttributeListAttributeCallback::~CHIPBridgedActionsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBridgedActionsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBridgedActionsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBridgedActionsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPBridgedDeviceBasicAttributeListAttributeCallback::CHIPBridgedDeviceBasicAttributeListAttributeCallback(jobject javaCallback,
                                                                                                           bool keepAlive) :
    chip::Callback::Callback<CHIPBridgedDeviceBasicClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPBridgedDeviceBasicAttributeListAttributeCallback::~CHIPBridgedDeviceBasicAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPBridgedDeviceBasicAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPBridgedDeviceBasicAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPBridgedDeviceBasicAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPChannelChannelListAttributeCallback::CHIPChannelChannelListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPChannelClusterChannelListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPChannelChannelListAttributeCallback::~CHIPChannelChannelListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPChannelChannelListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::Channel::Structs::ChannelInfo::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPChannelChannelListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPChannelChannelListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ChannelCluster$ChannelListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$ChannelCluster$ChannelListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>",
                         "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find ChannelListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool majorNumberNull     = false;
        bool majorNumberHasValue = true;

        uint16_t majorNumberValue = entry.majorNumber;

        jobject majorNumber = nullptr;
        if (!majorNumberNull && majorNumberHasValue)
        {
            jclass majorNumberEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", majorNumberEntryCls);
            chip::JniClass majorNumberJniClass(majorNumberEntryCls);
            jmethodID majorNumberEntryTypeCtor = env->GetMethodID(majorNumberEntryCls, "<init>", "(I)V");
            majorNumber                        = env->NewObject(majorNumberEntryCls, majorNumberEntryTypeCtor, majorNumberValue);
        }

        bool minorNumberNull     = false;
        bool minorNumberHasValue = true;

        uint16_t minorNumberValue = entry.minorNumber;

        jobject minorNumber = nullptr;
        if (!minorNumberNull && minorNumberHasValue)
        {
            jclass minorNumberEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", minorNumberEntryCls);
            chip::JniClass minorNumberJniClass(minorNumberEntryCls);
            jmethodID minorNumberEntryTypeCtor = env->GetMethodID(minorNumberEntryCls, "<init>", "(I)V");
            minorNumber                        = env->NewObject(minorNumberEntryCls, minorNumberEntryTypeCtor, minorNumberValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool callSignNull     = false;
        bool callSignHasValue = true;

        chip::CharSpan callSignValue = entry.callSign;

        jstring callSign = nullptr;
        chip::UtfString callSignStr(env, callSignValue);
        if (!callSignNull && callSignHasValue)
        {
            callSign = jstring(callSignStr.jniValue());
        }

        bool affiliateCallSignNull     = false;
        bool affiliateCallSignHasValue = true;

        chip::CharSpan affiliateCallSignValue = entry.affiliateCallSign;

        jstring affiliateCallSign = nullptr;
        chip::UtfString affiliateCallSignStr(env, affiliateCallSignValue);
        if (!affiliateCallSignNull && affiliateCallSignHasValue)
        {
            affiliateCallSign = jstring(affiliateCallSignStr.jniValue());
        }

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, majorNumber, minorNumber, name, callSign, affiliateCallSign);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create ChannelListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ChannelListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPChannelAttributeListAttributeCallback::CHIPChannelAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPChannelClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPChannelAttributeListAttributeCallback::~CHIPChannelAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPChannelAttributeListAttributeCallback::CallbackFn(void * context,
                                                           const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPChannelAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPChannelAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPColorControlAttributeListAttributeCallback::CHIPColorControlAttributeListAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPColorControlClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPColorControlAttributeListAttributeCallback::~CHIPColorControlAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPColorControlAttributeListAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPColorControlAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPColorControlAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPContentLauncherAcceptHeaderListAttributeCallback::CHIPContentLauncherAcceptHeaderListAttributeCallback(jobject javaCallback,
                                                                                                           bool keepAlive) :
    chip::Callback::Callback<CHIPContentLauncherClusterAcceptHeaderListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPContentLauncherAcceptHeaderListAttributeCallback::~CHIPContentLauncherAcceptHeaderListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPContentLauncherAcceptHeaderListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::CharSpan> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPContentLauncherAcceptHeaderListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPContentLauncherAcceptHeaderListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry              = iter.GetValue();
        bool entryNull            = false;
        chip::CharSpan entryValue = entry;

        jstring entryObject = nullptr;
        chip::UtfString entryStr(env, entryValue);
        if (!entryNull)
        {
            entryObject = jstring(entryStr.jniValue());
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AcceptHeaderListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPContentLauncherAttributeListAttributeCallback::CHIPContentLauncherAttributeListAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPContentLauncherClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPContentLauncherAttributeListAttributeCallback::~CHIPContentLauncherAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPContentLauncherAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPContentLauncherAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPContentLauncherAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDescriptorDeviceListAttributeCallback::CHIPDescriptorDeviceListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDescriptorClusterDeviceListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDescriptorDeviceListAttributeCallback::~CHIPDescriptorDeviceListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDescriptorDeviceListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::Descriptor::Structs::DeviceType::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDescriptorDeviceListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDescriptorDeviceListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$DescriptorCluster$DeviceListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$DescriptorCluster$DeviceListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Long;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find DeviceListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool typeNull     = false;
        bool typeHasValue = true;

        chip::DeviceTypeId typeValue = entry.type;

        jobject type = nullptr;
        if (!typeNull && typeHasValue)
        {
            jclass typeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", typeEntryCls);
            chip::JniClass typeJniClass(typeEntryCls);
            jmethodID typeEntryTypeCtor = env->GetMethodID(typeEntryCls, "<init>", "(J)V");
            type                        = env->NewObject(typeEntryCls, typeEntryTypeCtor, typeValue);
        }

        bool revisionNull     = false;
        bool revisionHasValue = true;

        uint16_t revisionValue = entry.revision;

        jobject revision = nullptr;
        if (!revisionNull && revisionHasValue)
        {
            jclass revisionEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", revisionEntryCls);
            chip::JniClass revisionJniClass(revisionEntryCls);
            jmethodID revisionEntryTypeCtor = env->GetMethodID(revisionEntryCls, "<init>", "(I)V");
            revision                        = env->NewObject(revisionEntryCls, revisionEntryTypeCtor, revisionValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, type, revision);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create DeviceListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding DeviceListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDescriptorServerListAttributeCallback::CHIPDescriptorServerListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDescriptorClusterServerListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDescriptorServerListAttributeCallback::~CHIPDescriptorServerListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDescriptorServerListAttributeCallback::CallbackFn(void * context,
                                                           const chip::app::DataModel::DecodableList<chip::ClusterId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDescriptorServerListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDescriptorServerListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry               = iter.GetValue();
        bool entryNull             = false;
        chip::ClusterId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ServerListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDescriptorClientListAttributeCallback::CHIPDescriptorClientListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDescriptorClusterClientListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDescriptorClientListAttributeCallback::~CHIPDescriptorClientListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDescriptorClientListAttributeCallback::CallbackFn(void * context,
                                                           const chip::app::DataModel::DecodableList<chip::ClusterId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDescriptorClientListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDescriptorClientListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry               = iter.GetValue();
        bool entryNull             = false;
        chip::ClusterId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ClientListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDescriptorPartsListAttributeCallback::CHIPDescriptorPartsListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDescriptorClusterPartsListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDescriptorPartsListAttributeCallback::~CHIPDescriptorPartsListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDescriptorPartsListAttributeCallback::CallbackFn(void * context,
                                                          const chip::app::DataModel::DecodableList<chip::EndpointId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDescriptorPartsListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDescriptorPartsListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                = iter.GetValue();
        bool entryNull              = false;
        chip::EndpointId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding PartsListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDescriptorAttributeListAttributeCallback::CHIPDescriptorAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDescriptorClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDescriptorAttributeListAttributeCallback::~CHIPDescriptorAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDescriptorAttributeListAttributeCallback::CallbackFn(void * context,
                                                              const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDescriptorAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDescriptorAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDiagnosticLogsAttributeListAttributeCallback::CHIPDiagnosticLogsAttributeListAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPDiagnosticLogsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDiagnosticLogsAttributeListAttributeCallback::~CHIPDiagnosticLogsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDiagnosticLogsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDiagnosticLogsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDiagnosticLogsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPDoorLockLockStateAttributeCallback::CHIPDoorLockLockStateAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDoorLockClusterLockStateAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDoorLockLockStateAttributeCallback::~CHIPDoorLockLockStateAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDoorLockLockStateAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlLockState> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPDoorLockLockStateAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDoorLockLockStateAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::app::Clusters::DoorLock::DlLockState>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPDoorLockDoorStateAttributeCallback::CHIPDoorLockDoorStateAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDoorLockClusterDoorStateAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDoorLockDoorStateAttributeCallback::~CHIPDoorLockDoorStateAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDoorLockDoorStateAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::DlDoorState> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPDoorLockDoorStateAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDoorLockDoorStateAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::app::Clusters::DoorLock::DlDoorState>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPDoorLockAttributeListAttributeCallback::CHIPDoorLockAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPDoorLockClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPDoorLockAttributeListAttributeCallback::~CHIPDoorLockAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPDoorLockAttributeListAttributeCallback::CallbackFn(void * context,
                                                            const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPDoorLockAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPDoorLockAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPElectricalMeasurementAttributeListAttributeCallback::CHIPElectricalMeasurementAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPElectricalMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPElectricalMeasurementAttributeListAttributeCallback::~CHIPElectricalMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPElectricalMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPElectricalMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPElectricalMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback::CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPEthernetNetworkDiagnosticsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback::~CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPEthernetNetworkDiagnosticsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPFixedLabelLabelListAttributeCallback::CHIPFixedLabelLabelListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPFixedLabelClusterLabelListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPFixedLabelLabelListAttributeCallback::~CHIPFixedLabelLabelListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPFixedLabelLabelListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::FixedLabel::Structs::LabelStruct::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPFixedLabelLabelListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPFixedLabelLabelListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$FixedLabelCluster$LabelListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$FixedLabelCluster$LabelListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find LabelListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool labelNull     = false;
        bool labelHasValue = true;

        chip::CharSpan labelValue = entry.label;

        jstring label = nullptr;
        chip::UtfString labelStr(env, labelValue);
        if (!labelNull && labelHasValue)
        {
            label = jstring(labelStr.jniValue());
        }

        bool valueNull     = false;
        bool valueHasValue = true;

        chip::CharSpan valueValue = entry.value;

        jstring value = nullptr;
        chip::UtfString valueStr(env, valueValue);
        if (!valueNull && valueHasValue)
        {
            value = jstring(valueStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, label, value);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create LabelListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding LabelListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPFixedLabelAttributeListAttributeCallback::CHIPFixedLabelAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPFixedLabelClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPFixedLabelAttributeListAttributeCallback::~CHIPFixedLabelAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPFixedLabelAttributeListAttributeCallback::CallbackFn(void * context,
                                                              const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPFixedLabelAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPFixedLabelAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPFlowMeasurementAttributeListAttributeCallback::CHIPFlowMeasurementAttributeListAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPFlowMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPFlowMeasurementAttributeListAttributeCallback::~CHIPFlowMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPFlowMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPFlowMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPFlowMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback::
    CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralCommissioningClusterBasicCommissioningInfoListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback::
    ~CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::GeneralCommissioning::Structs::BasicCommissioningInfoType::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralCommissioningBasicCommissioningInfoListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$GeneralCommissioningCluster$BasicCommissioningInfoListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class "
                     "chip/devicecontroller/ChipClusters$GeneralCommissioningCluster$BasicCommissioningInfoListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Long;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find BasicCommissioningInfoListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool failSafeExpiryLengthMsNull     = false;
        bool failSafeExpiryLengthMsHasValue = true;

        uint32_t failSafeExpiryLengthMsValue = entry.failSafeExpiryLengthMs;

        jobject failSafeExpiryLengthMs = nullptr;
        if (!failSafeExpiryLengthMsNull && failSafeExpiryLengthMsHasValue)
        {
            jclass failSafeExpiryLengthMsEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", failSafeExpiryLengthMsEntryCls);
            chip::JniClass failSafeExpiryLengthMsJniClass(failSafeExpiryLengthMsEntryCls);
            jmethodID failSafeExpiryLengthMsEntryTypeCtor = env->GetMethodID(failSafeExpiryLengthMsEntryCls, "<init>", "(J)V");
            failSafeExpiryLengthMs =
                env->NewObject(failSafeExpiryLengthMsEntryCls, failSafeExpiryLengthMsEntryTypeCtor, failSafeExpiryLengthMsValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, failSafeExpiryLengthMs);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create BasicCommissioningInfoListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding BasicCommissioningInfoListAttribute value: %" CHIP_ERROR_FORMAT,
                                iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralCommissioningAttributeListAttributeCallback::CHIPGeneralCommissioningAttributeListAttributeCallback(jobject javaCallback,
                                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralCommissioningClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralCommissioningAttributeListAttributeCallback::~CHIPGeneralCommissioningAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralCommissioningAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralCommissioningAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralCommissioningAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback::CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralDiagnosticsClusterNetworkInterfacesAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback::~CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::GeneralDiagnostics::Structs::NetworkInterfaceType::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralDiagnosticsNetworkInterfacesAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$GeneralDiagnosticsCluster$NetworkInterfacesAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl, "Could not find class chip/devicecontroller/ChipClusters$GeneralDiagnosticsCluster$NetworkInterfacesAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>",
                         "(Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;[BLjava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find NetworkInterfacesAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool fabricConnectedNull     = false;
        bool fabricConnectedHasValue = true;

        bool fabricConnectedValue = entry.fabricConnected;

        jobject fabricConnected = nullptr;
        if (!fabricConnectedNull && fabricConnectedHasValue)
        {
            jclass fabricConnectedEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", fabricConnectedEntryCls);
            chip::JniClass fabricConnectedJniClass(fabricConnectedEntryCls);
            jmethodID fabricConnectedEntryTypeCtor = env->GetMethodID(fabricConnectedEntryCls, "<init>", "(Z)V");
            fabricConnected = env->NewObject(fabricConnectedEntryCls, fabricConnectedEntryTypeCtor, fabricConnectedValue);
        }

        bool offPremiseServicesReachableIPv4Null     = false;
        bool offPremiseServicesReachableIPv4HasValue = true;

        bool offPremiseServicesReachableIPv4Value = entry.offPremiseServicesReachableIPv4;

        jobject offPremiseServicesReachableIPv4 = nullptr;
        if (!offPremiseServicesReachableIPv4Null && offPremiseServicesReachableIPv4HasValue)
        {
            jclass offPremiseServicesReachableIPv4EntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", offPremiseServicesReachableIPv4EntryCls);
            chip::JniClass offPremiseServicesReachableIPv4JniClass(offPremiseServicesReachableIPv4EntryCls);
            jmethodID offPremiseServicesReachableIPv4EntryTypeCtor =
                env->GetMethodID(offPremiseServicesReachableIPv4EntryCls, "<init>", "(Z)V");
            offPremiseServicesReachableIPv4 =
                env->NewObject(offPremiseServicesReachableIPv4EntryCls, offPremiseServicesReachableIPv4EntryTypeCtor,
                               offPremiseServicesReachableIPv4Value);
        }

        bool offPremiseServicesReachableIPv6Null     = false;
        bool offPremiseServicesReachableIPv6HasValue = true;

        bool offPremiseServicesReachableIPv6Value = entry.offPremiseServicesReachableIPv6;

        jobject offPremiseServicesReachableIPv6 = nullptr;
        if (!offPremiseServicesReachableIPv6Null && offPremiseServicesReachableIPv6HasValue)
        {
            jclass offPremiseServicesReachableIPv6EntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", offPremiseServicesReachableIPv6EntryCls);
            chip::JniClass offPremiseServicesReachableIPv6JniClass(offPremiseServicesReachableIPv6EntryCls);
            jmethodID offPremiseServicesReachableIPv6EntryTypeCtor =
                env->GetMethodID(offPremiseServicesReachableIPv6EntryCls, "<init>", "(Z)V");
            offPremiseServicesReachableIPv6 =
                env->NewObject(offPremiseServicesReachableIPv6EntryCls, offPremiseServicesReachableIPv6EntryTypeCtor,
                               offPremiseServicesReachableIPv6Value);
        }

        bool hardwareAddressNull     = false;
        bool hardwareAddressHasValue = true;

        chip::ByteSpan hardwareAddressValue = entry.hardwareAddress;

        jbyteArray hardwareAddress = nullptr;
        if (!hardwareAddressNull && hardwareAddressHasValue)
        {
            hardwareAddress = env->NewByteArray(hardwareAddressValue.size());
            env->SetByteArrayRegion(hardwareAddress, 0, hardwareAddressValue.size(),
                                    reinterpret_cast<const jbyte *>(hardwareAddressValue.data()));
        }

        bool typeNull     = false;
        bool typeHasValue = true;

        chip::app::Clusters::GeneralDiagnostics::InterfaceType typeValue = entry.type;

        jobject type = nullptr;
        if (!typeNull && typeHasValue)
        {
            jclass typeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", typeEntryCls);
            chip::JniClass typeJniClass(typeEntryCls);
            jmethodID typeEntryTypeCtor = env->GetMethodID(typeEntryCls, "<init>", "(I)V");
            type                        = env->NewObject(typeEntryCls, typeEntryTypeCtor, typeValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, name, fabricConnected, offPremiseServicesReachableIPv4,
                                              offPremiseServicesReachableIPv6, hardwareAddress, type);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create NetworkInterfacesAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding NetworkInterfacesAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback::CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralDiagnosticsClusterActiveHardwareFaultsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback::~CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralDiagnosticsActiveHardwareFaultsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ActiveHardwareFaultsAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback::CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralDiagnosticsClusterActiveRadioFaultsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback::~CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback::CallbackFn(void * context,
                                                                          const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralDiagnosticsActiveRadioFaultsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ActiveRadioFaultsAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback::CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralDiagnosticsClusterActiveNetworkFaultsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback::~CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralDiagnosticsActiveNetworkFaultsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ActiveNetworkFaultsAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGeneralDiagnosticsAttributeListAttributeCallback::CHIPGeneralDiagnosticsAttributeListAttributeCallback(jobject javaCallback,
                                                                                                           bool keepAlive) :
    chip::Callback::Callback<CHIPGeneralDiagnosticsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGeneralDiagnosticsAttributeListAttributeCallback::~CHIPGeneralDiagnosticsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGeneralDiagnosticsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGeneralDiagnosticsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGeneralDiagnosticsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGroupKeyManagementGroupKeyMapAttributeCallback::CHIPGroupKeyManagementGroupKeyMapAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPGroupKeyManagementClusterGroupKeyMapAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGroupKeyManagementGroupKeyMapAttributeCallback::~CHIPGroupKeyManagementGroupKeyMapAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGroupKeyManagementGroupKeyMapAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::GroupKeyManagement::Structs::GroupKey::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGroupKeyManagementGroupKeyMapAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGroupKeyManagementGroupKeyMapAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$GroupKeyManagementCluster$GroupKeyMapAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class chip/devicecontroller/ChipClusters$GroupKeyManagementCluster$GroupKeyMapAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find GroupKeyMapAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        uint16_t fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool groupIdNull     = false;
        bool groupIdHasValue = true;

        uint16_t groupIdValue = entry.groupId;

        jobject groupId = nullptr;
        if (!groupIdNull && groupIdHasValue)
        {
            jclass groupIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", groupIdEntryCls);
            chip::JniClass groupIdJniClass(groupIdEntryCls);
            jmethodID groupIdEntryTypeCtor = env->GetMethodID(groupIdEntryCls, "<init>", "(I)V");
            groupId                        = env->NewObject(groupIdEntryCls, groupIdEntryTypeCtor, groupIdValue);
        }

        bool groupKeySetIDNull     = false;
        bool groupKeySetIDHasValue = true;

        uint16_t groupKeySetIDValue = entry.groupKeySetID;

        jobject groupKeySetID = nullptr;
        if (!groupKeySetIDNull && groupKeySetIDHasValue)
        {
            jclass groupKeySetIDEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", groupKeySetIDEntryCls);
            chip::JniClass groupKeySetIDJniClass(groupKeySetIDEntryCls);
            jmethodID groupKeySetIDEntryTypeCtor = env->GetMethodID(groupKeySetIDEntryCls, "<init>", "(I)V");
            groupKeySetID = env->NewObject(groupKeySetIDEntryCls, groupKeySetIDEntryTypeCtor, groupKeySetIDValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, groupId, groupKeySetID);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create GroupKeyMapAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding GroupKeyMapAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGroupKeyManagementGroupTableAttributeCallback::CHIPGroupKeyManagementGroupTableAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPGroupKeyManagementClusterGroupTableAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGroupKeyManagementGroupTableAttributeCallback::~CHIPGroupKeyManagementGroupTableAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGroupKeyManagementGroupTableAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::GroupKeyManagement::Structs::GroupInfo::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGroupKeyManagementGroupTableAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGroupKeyManagementGroupTableAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$GroupKeyManagementCluster$GroupTableAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$GroupKeyManagementCluster$GroupTableAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find GroupTableAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        uint16_t fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool groupIdNull     = false;
        bool groupIdHasValue = true;

        uint16_t groupIdValue = entry.groupId;

        jobject groupId = nullptr;
        if (!groupIdNull && groupIdHasValue)
        {
            jclass groupIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", groupIdEntryCls);
            chip::JniClass groupIdJniClass(groupIdEntryCls);
            jmethodID groupIdEntryTypeCtor = env->GetMethodID(groupIdEntryCls, "<init>", "(I)V");
            groupId                        = env->NewObject(groupIdEntryCls, groupIdEntryTypeCtor, groupIdValue);
        }

        bool groupNameNull     = false;
        bool groupNameHasValue = true;

        chip::CharSpan groupNameValue = entry.groupName;

        jstring groupName = nullptr;
        chip::UtfString groupNameStr(env, groupNameValue);
        if (!groupNameNull && groupNameHasValue)
        {
            groupName = jstring(groupNameStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, groupId, groupName);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create GroupTableAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding GroupTableAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGroupKeyManagementAttributeListAttributeCallback::CHIPGroupKeyManagementAttributeListAttributeCallback(jobject javaCallback,
                                                                                                           bool keepAlive) :
    chip::Callback::Callback<CHIPGroupKeyManagementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGroupKeyManagementAttributeListAttributeCallback::~CHIPGroupKeyManagementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGroupKeyManagementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGroupKeyManagementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGroupKeyManagementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPGroupsAttributeListAttributeCallback::CHIPGroupsAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPGroupsClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPGroupsAttributeListAttributeCallback::~CHIPGroupsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPGroupsAttributeListAttributeCallback::CallbackFn(void * context,
                                                          const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPGroupsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPGroupsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPIdentifyAttributeListAttributeCallback::CHIPIdentifyAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIdentifyClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIdentifyAttributeListAttributeCallback::~CHIPIdentifyAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIdentifyAttributeListAttributeCallback::CallbackFn(void * context,
                                                            const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPIdentifyAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIdentifyAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPIlluminanceMeasurementMeasuredValueAttributeCallback::CHIPIlluminanceMeasurementMeasuredValueAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIlluminanceMeasurementClusterMeasuredValueAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIlluminanceMeasurementMeasuredValueAttributeCallback::~CHIPIlluminanceMeasurementMeasuredValueAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIlluminanceMeasurementMeasuredValueAttributeCallback::CallbackFn(void * context,
                                                                          const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPIlluminanceMeasurementMeasuredValueAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIlluminanceMeasurementMeasuredValueAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback::CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIlluminanceMeasurementClusterMinMeasuredValueAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback::~CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback::CallbackFn(void * context,
                                                                             const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIlluminanceMeasurementMinMeasuredValueAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback::CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIlluminanceMeasurementClusterMaxMeasuredValueAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback::~CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback::CallbackFn(void * context,
                                                                             const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIlluminanceMeasurementMaxMeasuredValueAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback::CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIlluminanceMeasurementClusterLightSensorTypeAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback::~CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback::CallbackFn(void * context,
                                                                            const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIlluminanceMeasurementLightSensorTypeAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPIlluminanceMeasurementAttributeListAttributeCallback::CHIPIlluminanceMeasurementAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPIlluminanceMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPIlluminanceMeasurementAttributeListAttributeCallback::~CHIPIlluminanceMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPIlluminanceMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPIlluminanceMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPIlluminanceMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPKeypadInputAttributeListAttributeCallback::CHIPKeypadInputAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPKeypadInputClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPKeypadInputAttributeListAttributeCallback::~CHIPKeypadInputAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPKeypadInputAttributeListAttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPKeypadInputAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPKeypadInputAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPLevelControlOnLevelAttributeCallback::CHIPLevelControlOnLevelAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPLevelControlClusterOnLevelAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLevelControlOnLevelAttributeCallback::~CHIPLevelControlOnLevelAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLevelControlOnLevelAttributeCallback::CallbackFn(void * context, const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPLevelControlOnLevelAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLevelControlOnLevelAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPLevelControlOnTransitionTimeAttributeCallback::CHIPLevelControlOnTransitionTimeAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPLevelControlClusterOnTransitionTimeAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLevelControlOnTransitionTimeAttributeCallback::~CHIPLevelControlOnTransitionTimeAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLevelControlOnTransitionTimeAttributeCallback::CallbackFn(void * context,
                                                                   const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPLevelControlOnTransitionTimeAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLevelControlOnTransitionTimeAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPLevelControlOffTransitionTimeAttributeCallback::CHIPLevelControlOffTransitionTimeAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPLevelControlClusterOffTransitionTimeAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLevelControlOffTransitionTimeAttributeCallback::~CHIPLevelControlOffTransitionTimeAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLevelControlOffTransitionTimeAttributeCallback::CallbackFn(void * context,
                                                                    const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPLevelControlOffTransitionTimeAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLevelControlOffTransitionTimeAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPLevelControlDefaultMoveRateAttributeCallback::CHIPLevelControlDefaultMoveRateAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPLevelControlClusterDefaultMoveRateAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLevelControlDefaultMoveRateAttributeCallback::~CHIPLevelControlDefaultMoveRateAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLevelControlDefaultMoveRateAttributeCallback::CallbackFn(void * context,
                                                                  const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPLevelControlDefaultMoveRateAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLevelControlDefaultMoveRateAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPLevelControlAttributeListAttributeCallback::CHIPLevelControlAttributeListAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPLevelControlClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLevelControlAttributeListAttributeCallback::~CHIPLevelControlAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLevelControlAttributeListAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPLevelControlAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLevelControlAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPLowPowerAttributeListAttributeCallback::CHIPLowPowerAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPLowPowerClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPLowPowerAttributeListAttributeCallback::~CHIPLowPowerAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPLowPowerAttributeListAttributeCallback::CallbackFn(void * context,
                                                            const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPLowPowerAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPLowPowerAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPMediaInputMediaInputListAttributeCallback::CHIPMediaInputMediaInputListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPMediaInputClusterMediaInputListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPMediaInputMediaInputListAttributeCallback::~CHIPMediaInputMediaInputListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPMediaInputMediaInputListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::MediaInput::Structs::InputInfo::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPMediaInputMediaInputListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPMediaInputMediaInputListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$MediaInputCluster$MediaInputListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$MediaInputCluster$MediaInputListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find MediaInputListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool indexNull     = false;
        bool indexHasValue = true;

        uint8_t indexValue = entry.index;

        jobject index = nullptr;
        if (!indexNull && indexHasValue)
        {
            jclass indexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", indexEntryCls);
            chip::JniClass indexJniClass(indexEntryCls);
            jmethodID indexEntryTypeCtor = env->GetMethodID(indexEntryCls, "<init>", "(I)V");
            index                        = env->NewObject(indexEntryCls, indexEntryTypeCtor, indexValue);
        }

        bool inputTypeNull     = false;
        bool inputTypeHasValue = true;

        chip::app::Clusters::MediaInput::InputTypeEnum inputTypeValue = entry.inputType;

        jobject inputType = nullptr;
        if (!inputTypeNull && inputTypeHasValue)
        {
            jclass inputTypeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", inputTypeEntryCls);
            chip::JniClass inputTypeJniClass(inputTypeEntryCls);
            jmethodID inputTypeEntryTypeCtor = env->GetMethodID(inputTypeEntryCls, "<init>", "(I)V");
            inputType                        = env->NewObject(inputTypeEntryCls, inputTypeEntryTypeCtor, inputTypeValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool descriptionNull     = false;
        bool descriptionHasValue = true;

        chip::CharSpan descriptionValue = entry.description;

        jstring description = nullptr;
        chip::UtfString descriptionStr(env, descriptionValue);
        if (!descriptionNull && descriptionHasValue)
        {
            description = jstring(descriptionStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, index, inputType, name, description);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create MediaInputListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding MediaInputListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPMediaInputAttributeListAttributeCallback::CHIPMediaInputAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPMediaInputClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPMediaInputAttributeListAttributeCallback::~CHIPMediaInputAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPMediaInputAttributeListAttributeCallback::CallbackFn(void * context,
                                                              const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPMediaInputAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPMediaInputAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPMediaPlaybackAttributeListAttributeCallback::CHIPMediaPlaybackAttributeListAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPMediaPlaybackClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPMediaPlaybackAttributeListAttributeCallback::~CHIPMediaPlaybackAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPMediaPlaybackAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPMediaPlaybackAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPMediaPlaybackAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPModeSelectSupportedModesAttributeCallback::CHIPModeSelectSupportedModesAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPModeSelectClusterSupportedModesAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPModeSelectSupportedModesAttributeCallback::~CHIPModeSelectSupportedModesAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPModeSelectSupportedModesAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::ModeSelect::Structs::ModeOptionStruct::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPModeSelectSupportedModesAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPModeSelectSupportedModesAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ModeSelectCluster$SupportedModesAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$ModeSelectCluster$SupportedModesAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Long;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find SupportedModesAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool labelNull     = false;
        bool labelHasValue = true;

        chip::CharSpan labelValue = entry.label;

        jstring label = nullptr;
        chip::UtfString labelStr(env, labelValue);
        if (!labelNull && labelHasValue)
        {
            label = jstring(labelStr.jniValue());
        }

        bool modeNull     = false;
        bool modeHasValue = true;

        uint8_t modeValue = entry.mode;

        jobject mode = nullptr;
        if (!modeNull && modeHasValue)
        {
            jclass modeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", modeEntryCls);
            chip::JniClass modeJniClass(modeEntryCls);
            jmethodID modeEntryTypeCtor = env->GetMethodID(modeEntryCls, "<init>", "(I)V");
            mode                        = env->NewObject(modeEntryCls, modeEntryTypeCtor, modeValue);
        }

        bool semanticTagNull     = false;
        bool semanticTagHasValue = true;

        uint32_t semanticTagValue = entry.semanticTag;

        jobject semanticTag = nullptr;
        if (!semanticTagNull && semanticTagHasValue)
        {
            jclass semanticTagEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", semanticTagEntryCls);
            chip::JniClass semanticTagJniClass(semanticTagEntryCls);
            jmethodID semanticTagEntryTypeCtor = env->GetMethodID(semanticTagEntryCls, "<init>", "(J)V");
            semanticTag                        = env->NewObject(semanticTagEntryCls, semanticTagEntryTypeCtor, semanticTagValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, label, mode, semanticTag);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create SupportedModesAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding SupportedModesAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPModeSelectAttributeListAttributeCallback::CHIPModeSelectAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPModeSelectClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPModeSelectAttributeListAttributeCallback::~CHIPModeSelectAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPModeSelectAttributeListAttributeCallback::CallbackFn(void * context,
                                                              const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPModeSelectAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPModeSelectAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPNetworkCommissioningNetworksAttributeCallback::CHIPNetworkCommissioningNetworksAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPNetworkCommissioningClusterNetworksAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPNetworkCommissioningNetworksAttributeCallback::~CHIPNetworkCommissioningNetworksAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPNetworkCommissioningNetworksAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::NetworkCommissioning::Structs::NetworkInfo::DecodableType> &
        list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPNetworkCommissioningNetworksAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPNetworkCommissioningNetworksAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$NetworkCommissioningCluster$NetworksAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$NetworkCommissioningCluster$NetworksAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "([BLjava/lang/Boolean;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find NetworksAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool networkIDNull     = false;
        bool networkIDHasValue = true;

        chip::ByteSpan networkIDValue = entry.networkID;

        jbyteArray networkID = nullptr;
        if (!networkIDNull && networkIDHasValue)
        {
            networkID = env->NewByteArray(networkIDValue.size());
            env->SetByteArrayRegion(networkID, 0, networkIDValue.size(), reinterpret_cast<const jbyte *>(networkIDValue.data()));
        }

        bool connectedNull     = false;
        bool connectedHasValue = true;

        bool connectedValue = entry.connected;

        jobject connected = nullptr;
        if (!connectedNull && connectedHasValue)
        {
            jclass connectedEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", connectedEntryCls);
            chip::JniClass connectedJniClass(connectedEntryCls);
            jmethodID connectedEntryTypeCtor = env->GetMethodID(connectedEntryCls, "<init>", "(Z)V");
            connected                        = env->NewObject(connectedEntryCls, connectedEntryTypeCtor, connectedValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, networkID, connected);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create NetworksAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding NetworksAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback::CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOtaSoftwareUpdateProviderClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback::~CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOtaSoftwareUpdateProviderAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback::
    CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOtaSoftwareUpdateRequestorClusterDefaultOtaProvidersAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback::
    ~CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::OtaSoftwareUpdateRequestor::Structs::ProviderLocation::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOtaSoftwareUpdateRequestorDefaultOtaProvidersAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$OtaSoftwareUpdateRequestorCluster$DefaultOtaProvidersAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class "
                     "chip/devicecontroller/ChipClusters$OtaSoftwareUpdateRequestorCluster$DefaultOtaProvidersAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Long;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find DefaultOtaProvidersAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        chip::FabricIndex fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool providerNodeIDNull     = false;
        bool providerNodeIDHasValue = true;

        chip::NodeId providerNodeIDValue = entry.providerNodeID;

        jobject providerNodeID = nullptr;
        if (!providerNodeIDNull && providerNodeIDHasValue)
        {
            jclass providerNodeIDEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", providerNodeIDEntryCls);
            chip::JniClass providerNodeIDJniClass(providerNodeIDEntryCls);
            jmethodID providerNodeIDEntryTypeCtor = env->GetMethodID(providerNodeIDEntryCls, "<init>", "(J)V");
            providerNodeID = env->NewObject(providerNodeIDEntryCls, providerNodeIDEntryTypeCtor, providerNodeIDValue);
        }

        bool endpointNull     = false;
        bool endpointHasValue = true;

        chip::EndpointId endpointValue = entry.endpoint;

        jobject endpoint = nullptr;
        if (!endpointNull && endpointHasValue)
        {
            jclass endpointEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", endpointEntryCls);
            chip::JniClass endpointJniClass(endpointEntryCls);
            jmethodID endpointEntryTypeCtor = env->GetMethodID(endpointEntryCls, "<init>", "(I)V");
            endpoint                        = env->NewObject(endpointEntryCls, endpointEntryTypeCtor, endpointValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, providerNodeID, endpoint);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create DefaultOtaProvidersAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding DefaultOtaProvidersAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback::
    CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOtaSoftwareUpdateRequestorClusterUpdateStateProgressAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback::
    ~CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOtaSoftwareUpdateRequestorUpdateStateProgressAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback::CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOtaSoftwareUpdateRequestorClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback::~CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOtaSoftwareUpdateRequestorAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOccupancySensingAttributeListAttributeCallback::CHIPOccupancySensingAttributeListAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPOccupancySensingClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOccupancySensingAttributeListAttributeCallback::~CHIPOccupancySensingAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOccupancySensingAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOccupancySensingAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOccupancySensingAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOnOffAttributeListAttributeCallback::CHIPOnOffAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOnOffClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOnOffAttributeListAttributeCallback::~CHIPOnOffAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOnOffAttributeListAttributeCallback::CallbackFn(void * context,
                                                         const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOnOffAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOnOffAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOnOffSwitchConfigurationAttributeListAttributeCallback::CHIPOnOffSwitchConfigurationAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOnOffSwitchConfigurationClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOnOffSwitchConfigurationAttributeListAttributeCallback::~CHIPOnOffSwitchConfigurationAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOnOffSwitchConfigurationAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOnOffSwitchConfigurationAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOnOffSwitchConfigurationAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOperationalCredentialsFabricsListAttributeCallback::CHIPOperationalCredentialsFabricsListAttributeCallback(jobject javaCallback,
                                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPOperationalCredentialsClusterFabricsListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOperationalCredentialsFabricsListAttributeCallback::~CHIPOperationalCredentialsFabricsListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOperationalCredentialsFabricsListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::OperationalCredentials::Structs::FabricDescriptor::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOperationalCredentialsFabricsListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOperationalCredentialsFabricsListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$OperationalCredentialsCluster$FabricsListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class chip/devicecontroller/ChipClusters$OperationalCredentialsCluster$FabricsListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(
        attributeClass, "<init>", "(Ljava/lang/Integer;[BLjava/lang/Integer;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find FabricsListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        uint8_t fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(I)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool rootPublicKeyNull     = false;
        bool rootPublicKeyHasValue = true;

        chip::ByteSpan rootPublicKeyValue = entry.rootPublicKey;

        jbyteArray rootPublicKey = nullptr;
        if (!rootPublicKeyNull && rootPublicKeyHasValue)
        {
            rootPublicKey = env->NewByteArray(rootPublicKeyValue.size());
            env->SetByteArrayRegion(rootPublicKey, 0, rootPublicKeyValue.size(),
                                    reinterpret_cast<const jbyte *>(rootPublicKeyValue.data()));
        }

        bool vendorIdNull     = false;
        bool vendorIdHasValue = true;

        uint16_t vendorIdValue = entry.vendorId;

        jobject vendorId = nullptr;
        if (!vendorIdNull && vendorIdHasValue)
        {
            jclass vendorIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", vendorIdEntryCls);
            chip::JniClass vendorIdJniClass(vendorIdEntryCls);
            jmethodID vendorIdEntryTypeCtor = env->GetMethodID(vendorIdEntryCls, "<init>", "(I)V");
            vendorId                        = env->NewObject(vendorIdEntryCls, vendorIdEntryTypeCtor, vendorIdValue);
        }

        bool fabricIdNull     = false;
        bool fabricIdHasValue = true;

        chip::FabricId fabricIdValue = entry.fabricId;

        jobject fabricId = nullptr;
        if (!fabricIdNull && fabricIdHasValue)
        {
            jclass fabricIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", fabricIdEntryCls);
            chip::JniClass fabricIdJniClass(fabricIdEntryCls);
            jmethodID fabricIdEntryTypeCtor = env->GetMethodID(fabricIdEntryCls, "<init>", "(J)V");
            fabricId                        = env->NewObject(fabricIdEntryCls, fabricIdEntryTypeCtor, fabricIdValue);
        }

        bool nodeIdNull     = false;
        bool nodeIdHasValue = true;

        chip::NodeId nodeIdValue = entry.nodeId;

        jobject nodeId = nullptr;
        if (!nodeIdNull && nodeIdHasValue)
        {
            jclass nodeIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", nodeIdEntryCls);
            chip::JniClass nodeIdJniClass(nodeIdEntryCls);
            jmethodID nodeIdEntryTypeCtor = env->GetMethodID(nodeIdEntryCls, "<init>", "(J)V");
            nodeId                        = env->NewObject(nodeIdEntryCls, nodeIdEntryTypeCtor, nodeIdValue);
        }

        bool labelNull     = false;
        bool labelHasValue = true;

        chip::CharSpan labelValue = entry.label;

        jstring label = nullptr;
        chip::UtfString labelStr(env, labelValue);
        if (!labelNull && labelHasValue)
        {
            label = jstring(labelStr.jniValue());
        }

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, fabricIndex, rootPublicKey, vendorId, fabricId, nodeId, label);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create FabricsListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding FabricsListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback::
    CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOperationalCredentialsClusterTrustedRootCertificatesAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback::
    ~CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::ByteSpan> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOperationalCredentialsTrustedRootCertificatesAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry              = iter.GetValue();
        bool entryNull            = false;
        chip::ByteSpan entryValue = entry;

        jbyteArray entryObject = nullptr;
        if (!entryNull)
        {
            entryObject = env->NewByteArray(entryValue.size());
            env->SetByteArrayRegion(entryObject, 0, entryValue.size(), reinterpret_cast<const jbyte *>(entryValue.data()));
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding TrustedRootCertificatesAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback::CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOperationalCredentialsClusterCurrentFabricIndexAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback::~CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback::CallbackFn(void * context, chip::FabricIndex value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOperationalCredentialsCurrentFabricIndexAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::FabricIndex>(javaValueClassName.c_str(),
                                                                            javaValueCtorSignature.c_str(), value, javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPOperationalCredentialsAttributeListAttributeCallback::CHIPOperationalCredentialsAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPOperationalCredentialsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPOperationalCredentialsAttributeListAttributeCallback::~CHIPOperationalCredentialsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPOperationalCredentialsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPOperationalCredentialsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPOperationalCredentialsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPowerSourceActiveBatteryFaultsAttributeCallback::CHIPPowerSourceActiveBatteryFaultsAttributeCallback(jobject javaCallback,
                                                                                                         bool keepAlive) :
    chip::Callback::Callback<CHIPPowerSourceClusterActiveBatteryFaultsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPowerSourceActiveBatteryFaultsAttributeCallback::~CHIPPowerSourceActiveBatteryFaultsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPowerSourceActiveBatteryFaultsAttributeCallback::CallbackFn(void * context,
                                                                     const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPowerSourceActiveBatteryFaultsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPowerSourceActiveBatteryFaultsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ActiveBatteryFaultsAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPowerSourceAttributeListAttributeCallback::CHIPPowerSourceAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPPowerSourceClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPowerSourceAttributeListAttributeCallback::~CHIPPowerSourceAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPowerSourceAttributeListAttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPowerSourceAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPowerSourceAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPowerSourceConfigurationSourcesAttributeCallback::CHIPPowerSourceConfigurationSourcesAttributeCallback(jobject javaCallback,
                                                                                                           bool keepAlive) :
    chip::Callback::Callback<CHIPPowerSourceConfigurationClusterSourcesAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPowerSourceConfigurationSourcesAttributeCallback::~CHIPPowerSourceConfigurationSourcesAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPowerSourceConfigurationSourcesAttributeCallback::CallbackFn(void * context,
                                                                      const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPowerSourceConfigurationSourcesAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPowerSourceConfigurationSourcesAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding SourcesAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPowerSourceConfigurationAttributeListAttributeCallback::CHIPPowerSourceConfigurationAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPPowerSourceConfigurationClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPowerSourceConfigurationAttributeListAttributeCallback::~CHIPPowerSourceConfigurationAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPowerSourceConfigurationAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPowerSourceConfigurationAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPowerSourceConfigurationAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPressureMeasurementAttributeListAttributeCallback::CHIPPressureMeasurementAttributeListAttributeCallback(jobject javaCallback,
                                                                                                             bool keepAlive) :
    chip::Callback::Callback<CHIPPressureMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPressureMeasurementAttributeListAttributeCallback::~CHIPPressureMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPressureMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPressureMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPressureMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback::
    CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPPumpConfigurationAndControlClusterLifetimeRunningHoursAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback::
    ~CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<uint32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPumpConfigurationAndControlLifetimeRunningHoursAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback::
    CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPPumpConfigurationAndControlClusterLifetimeEnergyConsumedAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback::
    ~CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<uint32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPumpConfigurationAndControlLifetimeEnergyConsumedAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPPumpConfigurationAndControlAttributeListAttributeCallback::CHIPPumpConfigurationAndControlAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPPumpConfigurationAndControlClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPPumpConfigurationAndControlAttributeListAttributeCallback::~CHIPPumpConfigurationAndControlAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPPumpConfigurationAndControlAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPPumpConfigurationAndControlAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPPumpConfigurationAndControlAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPRelativeHumidityMeasurementAttributeListAttributeCallback::CHIPRelativeHumidityMeasurementAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPRelativeHumidityMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPRelativeHumidityMeasurementAttributeListAttributeCallback::~CHIPRelativeHumidityMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPRelativeHumidityMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPRelativeHumidityMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPRelativeHumidityMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPScenesAttributeListAttributeCallback::CHIPScenesAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPScenesClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPScenesAttributeListAttributeCallback::~CHIPScenesAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPScenesAttributeListAttributeCallback::CallbackFn(void * context,
                                                          const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPScenesAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPScenesAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback::CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback(jobject javaCallback,
                                                                                                             bool keepAlive) :
    chip::Callback::Callback<CHIPSoftwareDiagnosticsClusterThreadMetricsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback::~CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::SoftwareDiagnostics::Structs::ThreadMetrics::DecodableType> &
        list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPSoftwareDiagnosticsThreadMetricsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$SoftwareDiagnosticsCluster$ThreadMetricsAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class chip/devicecontroller/ChipClusters$SoftwareDiagnosticsCluster$ThreadMetricsAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(
        attributeClass, "<init>", "(Ljava/lang/Long;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find ThreadMetricsAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool idNull     = false;
        bool idHasValue = true;

        uint64_t idValue = entry.id;

        jobject id = nullptr;
        if (!idNull && idHasValue)
        {
            jclass idEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", idEntryCls);
            chip::JniClass idJniClass(idEntryCls);
            jmethodID idEntryTypeCtor = env->GetMethodID(idEntryCls, "<init>", "(J)V");
            id                        = env->NewObject(idEntryCls, idEntryTypeCtor, idValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        bool stackFreeCurrentNull     = false;
        bool stackFreeCurrentHasValue = true;

        uint32_t stackFreeCurrentValue = entry.stackFreeCurrent;

        jobject stackFreeCurrent = nullptr;
        if (!stackFreeCurrentNull && stackFreeCurrentHasValue)
        {
            jclass stackFreeCurrentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", stackFreeCurrentEntryCls);
            chip::JniClass stackFreeCurrentJniClass(stackFreeCurrentEntryCls);
            jmethodID stackFreeCurrentEntryTypeCtor = env->GetMethodID(stackFreeCurrentEntryCls, "<init>", "(J)V");
            stackFreeCurrent = env->NewObject(stackFreeCurrentEntryCls, stackFreeCurrentEntryTypeCtor, stackFreeCurrentValue);
        }

        bool stackFreeMinimumNull     = false;
        bool stackFreeMinimumHasValue = true;

        uint32_t stackFreeMinimumValue = entry.stackFreeMinimum;

        jobject stackFreeMinimum = nullptr;
        if (!stackFreeMinimumNull && stackFreeMinimumHasValue)
        {
            jclass stackFreeMinimumEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", stackFreeMinimumEntryCls);
            chip::JniClass stackFreeMinimumJniClass(stackFreeMinimumEntryCls);
            jmethodID stackFreeMinimumEntryTypeCtor = env->GetMethodID(stackFreeMinimumEntryCls, "<init>", "(J)V");
            stackFreeMinimum = env->NewObject(stackFreeMinimumEntryCls, stackFreeMinimumEntryTypeCtor, stackFreeMinimumValue);
        }

        bool stackSizeNull     = false;
        bool stackSizeHasValue = true;

        uint32_t stackSizeValue = entry.stackSize;

        jobject stackSize = nullptr;
        if (!stackSizeNull && stackSizeHasValue)
        {
            jclass stackSizeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", stackSizeEntryCls);
            chip::JniClass stackSizeJniClass(stackSizeEntryCls);
            jmethodID stackSizeEntryTypeCtor = env->GetMethodID(stackSizeEntryCls, "<init>", "(J)V");
            stackSize                        = env->NewObject(stackSizeEntryCls, stackSizeEntryTypeCtor, stackSizeValue);
        }

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, id, name, stackFreeCurrent, stackFreeMinimum, stackSize);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create ThreadMetricsAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ThreadMetricsAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPSoftwareDiagnosticsAttributeListAttributeCallback::CHIPSoftwareDiagnosticsAttributeListAttributeCallback(jobject javaCallback,
                                                                                                             bool keepAlive) :
    chip::Callback::Callback<CHIPSoftwareDiagnosticsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPSoftwareDiagnosticsAttributeListAttributeCallback::~CHIPSoftwareDiagnosticsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPSoftwareDiagnosticsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPSoftwareDiagnosticsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPSoftwareDiagnosticsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPSwitchAttributeListAttributeCallback::CHIPSwitchAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPSwitchClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPSwitchAttributeListAttributeCallback::~CHIPSwitchAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPSwitchAttributeListAttributeCallback::CallbackFn(void * context,
                                                          const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPSwitchAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPSwitchAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTargetNavigatorTargetNavigatorListAttributeCallback::CHIPTargetNavigatorTargetNavigatorListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTargetNavigatorClusterTargetNavigatorListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTargetNavigatorTargetNavigatorListAttributeCallback::~CHIPTargetNavigatorTargetNavigatorListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTargetNavigatorTargetNavigatorListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::TargetNavigator::Structs::TargetInfo::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTargetNavigatorTargetNavigatorListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTargetNavigatorTargetNavigatorListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$TargetNavigatorCluster$TargetNavigatorListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl, "Could not find class chip/devicecontroller/ChipClusters$TargetNavigatorCluster$TargetNavigatorListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find TargetNavigatorListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool identifierNull     = false;
        bool identifierHasValue = true;

        uint8_t identifierValue = entry.identifier;

        jobject identifier = nullptr;
        if (!identifierNull && identifierHasValue)
        {
            jclass identifierEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", identifierEntryCls);
            chip::JniClass identifierJniClass(identifierEntryCls);
            jmethodID identifierEntryTypeCtor = env->GetMethodID(identifierEntryCls, "<init>", "(I)V");
            identifier                        = env->NewObject(identifierEntryCls, identifierEntryTypeCtor, identifierValue);
        }

        bool nameNull     = false;
        bool nameHasValue = true;

        chip::CharSpan nameValue = entry.name;

        jstring name = nullptr;
        chip::UtfString nameStr(env, nameValue);
        if (!nameNull && nameHasValue)
        {
            name = jstring(nameStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, identifier, name);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create TargetNavigatorListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding TargetNavigatorListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTargetNavigatorAttributeListAttributeCallback::CHIPTargetNavigatorAttributeListAttributeCallback(jobject javaCallback,
                                                                                                     bool keepAlive) :
    chip::Callback::Callback<CHIPTargetNavigatorClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTargetNavigatorAttributeListAttributeCallback::~CHIPTargetNavigatorAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTargetNavigatorAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTargetNavigatorAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTargetNavigatorAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTemperatureMeasurementAttributeListAttributeCallback::CHIPTemperatureMeasurementAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTemperatureMeasurementClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTemperatureMeasurementAttributeListAttributeCallback::~CHIPTemperatureMeasurementAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTemperatureMeasurementAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTemperatureMeasurementAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTemperatureMeasurementAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterListInt8uAttributeCallback::CHIPTestClusterListInt8uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterListInt8uAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterListInt8uAttributeCallback::~CHIPTestClusterListInt8uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterListInt8uAttributeCallback::CallbackFn(void * context,
                                                           const chip::app::DataModel::DecodableList<uint8_t> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterListInt8uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterListInt8uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry       = iter.GetValue();
        bool entryNull     = false;
        uint8_t entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ListInt8uAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterListOctetStringAttributeCallback::CHIPTestClusterListOctetStringAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterListOctetStringAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterListOctetStringAttributeCallback::~CHIPTestClusterListOctetStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterListOctetStringAttributeCallback::CallbackFn(void * context,
                                                                 const chip::app::DataModel::DecodableList<chip::ByteSpan> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterListOctetStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterListOctetStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry              = iter.GetValue();
        bool entryNull            = false;
        chip::ByteSpan entryValue = entry;

        jbyteArray entryObject = nullptr;
        if (!entryNull)
        {
            entryObject = env->NewByteArray(entryValue.size());
            env->SetByteArrayRegion(entryObject, 0, entryValue.size(), reinterpret_cast<const jbyte *>(entryValue.data()));
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ListOctetStringAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterListStructOctetStringAttributeCallback::CHIPTestClusterListStructOctetStringAttributeCallback(jobject javaCallback,
                                                                                                             bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterListStructOctetStringAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterListStructOctetStringAttributeCallback::~CHIPTestClusterListStructOctetStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterListStructOctetStringAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::TestCluster::Structs::TestListStructOctet::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterListStructOctetStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterListStructOctetStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$TestClusterCluster$ListStructOctetStringAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class chip/devicecontroller/ChipClusters$TestClusterCluster$ListStructOctetStringAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Long;[B)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find ListStructOctetStringAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool fabricIndexNull     = false;
        bool fabricIndexHasValue = true;

        uint64_t fabricIndexValue = entry.fabricIndex;

        jobject fabricIndex = nullptr;
        if (!fabricIndexNull && fabricIndexHasValue)
        {
            jclass fabricIndexEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", fabricIndexEntryCls);
            chip::JniClass fabricIndexJniClass(fabricIndexEntryCls);
            jmethodID fabricIndexEntryTypeCtor = env->GetMethodID(fabricIndexEntryCls, "<init>", "(J)V");
            fabricIndex                        = env->NewObject(fabricIndexEntryCls, fabricIndexEntryTypeCtor, fabricIndexValue);
        }

        bool operationalCertNull     = false;
        bool operationalCertHasValue = true;

        chip::ByteSpan operationalCertValue = entry.operationalCert;

        jbyteArray operationalCert = nullptr;
        if (!operationalCertNull && operationalCertHasValue)
        {
            operationalCert = env->NewByteArray(operationalCertValue.size());
            env->SetByteArrayRegion(operationalCert, 0, operationalCertValue.size(),
                                    reinterpret_cast<const jbyte *>(operationalCertValue.data()));
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, fabricIndex, operationalCert);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create ListStructOctetStringAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ListStructOctetStringAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterVendorIdAttributeCallback::CHIPTestClusterVendorIdAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterVendorIdAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterVendorIdAttributeCallback::~CHIPTestClusterVendorIdAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterVendorIdAttributeCallback::CallbackFn(void * context, chip::VendorId value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterVendorIdAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterVendorIdAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::VendorId>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                         value, javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback::CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterListNullablesAndOptionalsStructAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback::~CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::TestCluster::Structs::NullablesAndOptionalsStruct::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterListNullablesAndOptionalsStructAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$TestClusterCluster$ListNullablesAndOptionalsStructAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl,
            "Could not find class chip/devicecontroller/ChipClusters$TestClusterCluster$ListNullablesAndOptionalsStructAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(
        attributeClass, "<init>",
        "(Ljava/lang/Integer;Ljava/util/Optional;Ljava/util/Optional;Ljava/lang/String;Ljava/util/Optional;Ljava/util/Optional;)V");
    VerifyOrReturn(attributeCtor != nullptr,
                   ChipLogError(Zcl, "Could not find ListNullablesAndOptionalsStructAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool nullableIntNull     = false;
        bool nullableIntHasValue = true;
        uint16_t nullableIntValue;
        nullableIntNull = entry.nullableInt.IsNull();
        if (!nullableIntNull)
        {
            nullableIntValue = entry.nullableInt.Value();
        }

        jobject nullableInt = nullptr;
        if (!nullableIntNull && nullableIntHasValue)
        {
            jclass nullableIntEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", nullableIntEntryCls);
            chip::JniClass nullableIntJniClass(nullableIntEntryCls);
            jmethodID nullableIntEntryTypeCtor = env->GetMethodID(nullableIntEntryCls, "<init>", "(I)V");
            nullableInt                        = env->NewObject(nullableIntEntryCls, nullableIntEntryTypeCtor, nullableIntValue);
        }

        bool optionalIntNull     = false;
        bool optionalIntHasValue = true;

        uint16_t optionalIntValue;
        optionalIntHasValue = entry.optionalInt.HasValue();
        if (optionalIntHasValue)
        {
            optionalIntValue = entry.optionalInt.Value();
        }

        jobject optionalInt = nullptr;
        if (!optionalIntNull && optionalIntHasValue)
        {
            jclass optionalIntEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", optionalIntEntryCls);
            chip::JniClass optionalIntJniClass(optionalIntEntryCls);
            jmethodID optionalIntEntryTypeCtor = env->GetMethodID(optionalIntEntryCls, "<init>", "(I)V");
            optionalInt                        = env->NewObject(optionalIntEntryCls, optionalIntEntryTypeCtor, optionalIntValue);
        }

        jobject optionalIntOptional = nullptr;
        chip::JniReferences::GetInstance().CreateOptional(optionalInt, optionalIntOptional);
        bool nullableOptionalIntNull     = false;
        bool nullableOptionalIntHasValue = true;

        uint16_t nullableOptionalIntValue;
        nullableOptionalIntHasValue = entry.nullableOptionalInt.HasValue();
        if (nullableOptionalIntHasValue)
        {
            auto nullableOptionalIntValueFromOptional = entry.nullableOptionalInt.Value();
            nullableOptionalIntNull                   = nullableOptionalIntValueFromOptional.IsNull();
            if (!nullableOptionalIntNull)
            {
                nullableOptionalIntValue = nullableOptionalIntValueFromOptional.Value();
            }
        }

        jobject nullableOptionalInt = nullptr;
        if (!nullableOptionalIntNull && nullableOptionalIntHasValue)
        {
            jclass nullableOptionalIntEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", nullableOptionalIntEntryCls);
            chip::JniClass nullableOptionalIntJniClass(nullableOptionalIntEntryCls);
            jmethodID nullableOptionalIntEntryTypeCtor = env->GetMethodID(nullableOptionalIntEntryCls, "<init>", "(I)V");
            nullableOptionalInt =
                env->NewObject(nullableOptionalIntEntryCls, nullableOptionalIntEntryTypeCtor, nullableOptionalIntValue);
        }

        jobject nullableOptionalIntOptional = nullptr;
        chip::JniReferences::GetInstance().CreateOptional(nullableOptionalInt, nullableOptionalIntOptional);
        bool nullableStringNull     = false;
        bool nullableStringHasValue = true;
        chip::CharSpan nullableStringValue;
        nullableStringNull = entry.nullableString.IsNull();
        if (!nullableStringNull)
        {
            nullableStringValue = entry.nullableString.Value();
        }

        jstring nullableString = nullptr;
        chip::UtfString nullableStringStr(env, nullableStringValue);
        if (!nullableStringNull && nullableStringHasValue)
        {
            nullableString = jstring(nullableStringStr.jniValue());
        }

        bool optionalStringNull     = false;
        bool optionalStringHasValue = true;

        chip::CharSpan optionalStringValue;
        optionalStringHasValue = entry.optionalString.HasValue();
        if (optionalStringHasValue)
        {
            optionalStringValue = entry.optionalString.Value();
        }

        jstring optionalString = nullptr;
        chip::UtfString optionalStringStr(env, optionalStringValue);
        if (!optionalStringNull && optionalStringHasValue)
        {
            optionalString = jstring(optionalStringStr.jniValue());
        }

        jobject optionalStringOptional = nullptr;
        chip::JniReferences::GetInstance().CreateOptional(optionalString, optionalStringOptional);
        bool nullableOptionalStringNull     = false;
        bool nullableOptionalStringHasValue = true;

        chip::CharSpan nullableOptionalStringValue;
        nullableOptionalStringHasValue = entry.nullableOptionalString.HasValue();
        if (nullableOptionalStringHasValue)
        {
            auto nullableOptionalStringValueFromOptional = entry.nullableOptionalString.Value();
            nullableOptionalStringNull                   = nullableOptionalStringValueFromOptional.IsNull();
            if (!nullableOptionalStringNull)
            {
                nullableOptionalStringValue = nullableOptionalStringValueFromOptional.Value();
            }
        }

        jstring nullableOptionalString = nullptr;
        chip::UtfString nullableOptionalStringStr(env, nullableOptionalStringValue);
        if (!nullableOptionalStringNull && nullableOptionalStringHasValue)
        {
            nullableOptionalString = jstring(nullableOptionalStringStr.jniValue());
        }

        jobject nullableOptionalStringOptional = nullptr;
        chip::JniReferences::GetInstance().CreateOptional(nullableOptionalString, nullableOptionalStringOptional);

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, nullableInt, optionalIntOptional, nullableOptionalIntOptional,
                           nullableString, optionalStringOptional, nullableOptionalStringOptional);
        VerifyOrReturn(attributeObj != nullptr,
                       ChipLogError(Zcl, "Could not create ListNullablesAndOptionalsStructAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding ListNullablesAndOptionalsStructAttribute value: %" CHIP_ERROR_FORMAT,
                                iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterListLongOctetStringAttributeCallback::CHIPTestClusterListLongOctetStringAttributeCallback(jobject javaCallback,
                                                                                                         bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterListLongOctetStringAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterListLongOctetStringAttributeCallback::~CHIPTestClusterListLongOctetStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterListLongOctetStringAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::ByteSpan> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterListLongOctetStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterListLongOctetStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry              = iter.GetValue();
        bool entryNull            = false;
        chip::ByteSpan entryValue = entry;

        jbyteArray entryObject = nullptr;
        if (!entryNull)
        {
            entryObject = env->NewByteArray(entryValue.size());
            env->SetByteArrayRegion(entryObject, 0, entryValue.size(), reinterpret_cast<const jbyte *>(entryValue.data()));
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ListLongOctetStringAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPTestClusterNullableBooleanAttributeCallback::CHIPTestClusterNullableBooleanAttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableBooleanAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableBooleanAttributeCallback::~CHIPTestClusterNullableBooleanAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableBooleanAttributeCallback::CallbackFn(void * context, const chip::app::DataModel::Nullable<bool> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableBooleanAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableBooleanAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Boolean;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Boolean";
    std::string javaValueCtorSignature = "(Z)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<bool>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                               value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableBitmap8AttributeCallback::CHIPTestClusterNullableBitmap8AttributeCallback(jobject javaCallback,
                                                                                                 bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableBitmap8AttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableBitmap8AttributeCallback::~CHIPTestClusterNullableBitmap8AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableBitmap8AttributeCallback::CallbackFn(void * context,
                                                                 const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableBitmap8AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableBitmap8AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableBitmap16AttributeCallback::CHIPTestClusterNullableBitmap16AttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableBitmap16AttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableBitmap16AttributeCallback::~CHIPTestClusterNullableBitmap16AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableBitmap16AttributeCallback::CallbackFn(void * context,
                                                                  const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableBitmap16AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableBitmap16AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableBitmap32AttributeCallback::CHIPTestClusterNullableBitmap32AttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableBitmap32AttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableBitmap32AttributeCallback::~CHIPTestClusterNullableBitmap32AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableBitmap32AttributeCallback::CallbackFn(void * context,
                                                                  const chip::app::DataModel::Nullable<uint32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableBitmap32AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableBitmap32AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableBitmap64AttributeCallback::CHIPTestClusterNullableBitmap64AttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableBitmap64AttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableBitmap64AttributeCallback::~CHIPTestClusterNullableBitmap64AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableBitmap64AttributeCallback::CallbackFn(void * context,
                                                                  const chip::app::DataModel::Nullable<uint64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableBitmap64AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableBitmap64AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt8uAttributeCallback::CHIPTestClusterNullableInt8uAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt8uAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt8uAttributeCallback::~CHIPTestClusterNullableInt8uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt8uAttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt8uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt8uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt16uAttributeCallback::CHIPTestClusterNullableInt16uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt16uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt16uAttributeCallback::~CHIPTestClusterNullableInt16uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt16uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt16uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt16uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt24uAttributeCallback::CHIPTestClusterNullableInt24uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt24uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt24uAttributeCallback::~CHIPTestClusterNullableInt24uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt24uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt24uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt24uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt32uAttributeCallback::CHIPTestClusterNullableInt32uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt32uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt32uAttributeCallback::~CHIPTestClusterNullableInt32uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt32uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt32uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt32uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt40uAttributeCallback::CHIPTestClusterNullableInt40uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt40uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt40uAttributeCallback::~CHIPTestClusterNullableInt40uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt40uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt40uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt40uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt48uAttributeCallback::CHIPTestClusterNullableInt48uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt48uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt48uAttributeCallback::~CHIPTestClusterNullableInt48uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt48uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt48uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt48uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt56uAttributeCallback::CHIPTestClusterNullableInt56uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt56uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt56uAttributeCallback::~CHIPTestClusterNullableInt56uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt56uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt56uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt56uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt64uAttributeCallback::CHIPTestClusterNullableInt64uAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt64uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt64uAttributeCallback::~CHIPTestClusterNullableInt64uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt64uAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt64uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt64uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt8sAttributeCallback::CHIPTestClusterNullableInt8sAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt8sAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt8sAttributeCallback::~CHIPTestClusterNullableInt8sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt8sAttributeCallback::CallbackFn(void * context, const chip::app::DataModel::Nullable<int8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt8sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt8sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                 value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt16sAttributeCallback::CHIPTestClusterNullableInt16sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt16sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt16sAttributeCallback::~CHIPTestClusterNullableInt16sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt16sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt16sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt16sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt24sAttributeCallback::CHIPTestClusterNullableInt24sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt24sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt24sAttributeCallback::~CHIPTestClusterNullableInt24sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt24sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt24sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt24sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt32sAttributeCallback::CHIPTestClusterNullableInt32sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt32sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt32sAttributeCallback::~CHIPTestClusterNullableInt32sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt32sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int32_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt32sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt32sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int32_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt40sAttributeCallback::CHIPTestClusterNullableInt40sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt40sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt40sAttributeCallback::~CHIPTestClusterNullableInt40sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt40sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt40sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt40sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt48sAttributeCallback::CHIPTestClusterNullableInt48sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt48sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt48sAttributeCallback::~CHIPTestClusterNullableInt48sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt48sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt48sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt48sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt56sAttributeCallback::CHIPTestClusterNullableInt56sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt56sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt56sAttributeCallback::~CHIPTestClusterNullableInt56sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt56sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt56sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt56sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableInt64sAttributeCallback::CHIPTestClusterNullableInt64sAttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableInt64sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableInt64sAttributeCallback::~CHIPTestClusterNullableInt64sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableInt64sAttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<int64_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableInt64sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableInt64sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Long;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Long";
    std::string javaValueCtorSignature = "(J)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int64_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableEnum8AttributeCallback::CHIPTestClusterNullableEnum8AttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableEnum8AttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableEnum8AttributeCallback::~CHIPTestClusterNullableEnum8AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableEnum8AttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableEnum8AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableEnum8AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableEnum16AttributeCallback::CHIPTestClusterNullableEnum16AttributeCallback(jobject javaCallback,
                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableEnum16AttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableEnum16AttributeCallback::~CHIPTestClusterNullableEnum16AttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableEnum16AttributeCallback::CallbackFn(void * context,
                                                                const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableEnum16AttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableEnum16AttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableFloatSingleAttributeCallback::CHIPTestClusterNullableFloatSingleAttributeCallback(jobject javaCallback,
                                                                                                         bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableFloatSingleAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableFloatSingleAttributeCallback::~CHIPTestClusterNullableFloatSingleAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableFloatSingleAttributeCallback::CallbackFn(void * context,
                                                                     const chip::app::DataModel::Nullable<float> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableFloatSingleAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableFloatSingleAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Float;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Float";
    std::string javaValueCtorSignature = "(F)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<float>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableFloatDoubleAttributeCallback::CHIPTestClusterNullableFloatDoubleAttributeCallback(jobject javaCallback,
                                                                                                         bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableFloatDoubleAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableFloatDoubleAttributeCallback::~CHIPTestClusterNullableFloatDoubleAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableFloatDoubleAttributeCallback::CallbackFn(void * context,
                                                                     const chip::app::DataModel::Nullable<double> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableFloatDoubleAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableFloatDoubleAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Double;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Double";
    std::string javaValueCtorSignature = "(D)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<double>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                 value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableOctetStringAttributeCallback::CHIPTestClusterNullableOctetStringAttributeCallback(jobject javaCallback,
                                                                                                         bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableOctetStringAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableOctetStringAttributeCallback::~CHIPTestClusterNullableOctetStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableOctetStringAttributeCallback::CallbackFn(void * context,
                                                                     const chip::app::DataModel::Nullable<chip::ByteSpan> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableOctetStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableOctetStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "([B)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    chip::ByteArray javaValueByteArray(env, value.Value());
    javaValue = javaValueByteArray.jniValue();

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableCharStringAttributeCallback::CHIPTestClusterNullableCharStringAttributeCallback(jobject javaCallback,
                                                                                                       bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableCharStringAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableCharStringAttributeCallback::~CHIPTestClusterNullableCharStringAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableCharStringAttributeCallback::CallbackFn(void * context,
                                                                    const chip::app::DataModel::Nullable<chip::CharSpan> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableCharStringAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableCharStringAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/String;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    chip::UtfString javaValueUtfString(env, value.Value());
    javaValue = javaValueUtfString.jniValue();

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableEnumAttrAttributeCallback::CHIPTestClusterNullableEnumAttrAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableEnumAttrAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableEnumAttrAttributeCallback::~CHIPTestClusterNullableEnumAttrAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableEnumAttrAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::SimpleEnum> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableEnumAttrAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableEnumAttrAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::app::Clusters::TestCluster::SimpleEnum>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback::CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableRangeRestrictedInt8uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback::~CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback::CallbackFn(void * context,
                                                                              const chip::app::DataModel::Nullable<uint8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableRangeRestrictedInt8uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback::CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableRangeRestrictedInt8sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback::~CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback::CallbackFn(void * context,
                                                                              const chip::app::DataModel::Nullable<int8_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableRangeRestrictedInt8sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int8_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                 value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback::CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableRangeRestrictedInt16uAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback::~CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableRangeRestrictedInt16uAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback::CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterNullableRangeRestrictedInt16sAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback::~CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<int16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterNullableRangeRestrictedInt16sAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<int16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                  value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPTestClusterAttributeListAttributeCallback::CHIPTestClusterAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPTestClusterClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPTestClusterAttributeListAttributeCallback::~CHIPTestClusterAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPTestClusterAttributeListAttributeCallback::CallbackFn(void * context,
                                                               const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPTestClusterAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPTestClusterAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThermostatAttributeListAttributeCallback::CHIPThermostatAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThermostatClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThermostatAttributeListAttributeCallback::~CHIPThermostatAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThermostatAttributeListAttributeCallback::CallbackFn(void * context,
                                                              const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThermostatAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThermostatAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback::
    CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThermostatUserInterfaceConfigurationClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback::
    ~CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThermostatUserInterfaceConfigurationAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback::CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterNeighborTableListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback::~CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::ThreadNetworkDiagnostics::Structs::NeighborTable::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsNeighborTableListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$NeighborTableListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl,
            "Could not find class chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$NeighborTableListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>",
                         "(Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/"
                         "Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/"
                         "Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find NeighborTableListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool extAddressNull     = false;
        bool extAddressHasValue = true;

        uint64_t extAddressValue = entry.extAddress;

        jobject extAddress = nullptr;
        if (!extAddressNull && extAddressHasValue)
        {
            jclass extAddressEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", extAddressEntryCls);
            chip::JniClass extAddressJniClass(extAddressEntryCls);
            jmethodID extAddressEntryTypeCtor = env->GetMethodID(extAddressEntryCls, "<init>", "(J)V");
            extAddress                        = env->NewObject(extAddressEntryCls, extAddressEntryTypeCtor, extAddressValue);
        }

        bool ageNull     = false;
        bool ageHasValue = true;

        uint32_t ageValue = entry.age;

        jobject age = nullptr;
        if (!ageNull && ageHasValue)
        {
            jclass ageEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", ageEntryCls);
            chip::JniClass ageJniClass(ageEntryCls);
            jmethodID ageEntryTypeCtor = env->GetMethodID(ageEntryCls, "<init>", "(J)V");
            age                        = env->NewObject(ageEntryCls, ageEntryTypeCtor, ageValue);
        }

        bool rloc16Null     = false;
        bool rloc16HasValue = true;

        uint16_t rloc16Value = entry.rloc16;

        jobject rloc16 = nullptr;
        if (!rloc16Null && rloc16HasValue)
        {
            jclass rloc16EntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", rloc16EntryCls);
            chip::JniClass rloc16JniClass(rloc16EntryCls);
            jmethodID rloc16EntryTypeCtor = env->GetMethodID(rloc16EntryCls, "<init>", "(I)V");
            rloc16                        = env->NewObject(rloc16EntryCls, rloc16EntryTypeCtor, rloc16Value);
        }

        bool linkFrameCounterNull     = false;
        bool linkFrameCounterHasValue = true;

        uint32_t linkFrameCounterValue = entry.linkFrameCounter;

        jobject linkFrameCounter = nullptr;
        if (!linkFrameCounterNull && linkFrameCounterHasValue)
        {
            jclass linkFrameCounterEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", linkFrameCounterEntryCls);
            chip::JniClass linkFrameCounterJniClass(linkFrameCounterEntryCls);
            jmethodID linkFrameCounterEntryTypeCtor = env->GetMethodID(linkFrameCounterEntryCls, "<init>", "(J)V");
            linkFrameCounter = env->NewObject(linkFrameCounterEntryCls, linkFrameCounterEntryTypeCtor, linkFrameCounterValue);
        }

        bool mleFrameCounterNull     = false;
        bool mleFrameCounterHasValue = true;

        uint32_t mleFrameCounterValue = entry.mleFrameCounter;

        jobject mleFrameCounter = nullptr;
        if (!mleFrameCounterNull && mleFrameCounterHasValue)
        {
            jclass mleFrameCounterEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", mleFrameCounterEntryCls);
            chip::JniClass mleFrameCounterJniClass(mleFrameCounterEntryCls);
            jmethodID mleFrameCounterEntryTypeCtor = env->GetMethodID(mleFrameCounterEntryCls, "<init>", "(J)V");
            mleFrameCounter = env->NewObject(mleFrameCounterEntryCls, mleFrameCounterEntryTypeCtor, mleFrameCounterValue);
        }

        bool lqiNull     = false;
        bool lqiHasValue = true;

        uint8_t lqiValue = entry.lqi;

        jobject lqi = nullptr;
        if (!lqiNull && lqiHasValue)
        {
            jclass lqiEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", lqiEntryCls);
            chip::JniClass lqiJniClass(lqiEntryCls);
            jmethodID lqiEntryTypeCtor = env->GetMethodID(lqiEntryCls, "<init>", "(I)V");
            lqi                        = env->NewObject(lqiEntryCls, lqiEntryTypeCtor, lqiValue);
        }

        bool averageRssiNull     = false;
        bool averageRssiHasValue = true;

        int8_t averageRssiValue = entry.averageRssi;

        jobject averageRssi = nullptr;
        if (!averageRssiNull && averageRssiHasValue)
        {
            jclass averageRssiEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", averageRssiEntryCls);
            chip::JniClass averageRssiJniClass(averageRssiEntryCls);
            jmethodID averageRssiEntryTypeCtor = env->GetMethodID(averageRssiEntryCls, "<init>", "(I)V");
            averageRssi                        = env->NewObject(averageRssiEntryCls, averageRssiEntryTypeCtor, averageRssiValue);
        }

        bool lastRssiNull     = false;
        bool lastRssiHasValue = true;

        int8_t lastRssiValue = entry.lastRssi;

        jobject lastRssi = nullptr;
        if (!lastRssiNull && lastRssiHasValue)
        {
            jclass lastRssiEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", lastRssiEntryCls);
            chip::JniClass lastRssiJniClass(lastRssiEntryCls);
            jmethodID lastRssiEntryTypeCtor = env->GetMethodID(lastRssiEntryCls, "<init>", "(I)V");
            lastRssi                        = env->NewObject(lastRssiEntryCls, lastRssiEntryTypeCtor, lastRssiValue);
        }

        bool frameErrorRateNull     = false;
        bool frameErrorRateHasValue = true;

        uint8_t frameErrorRateValue = entry.frameErrorRate;

        jobject frameErrorRate = nullptr;
        if (!frameErrorRateNull && frameErrorRateHasValue)
        {
            jclass frameErrorRateEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", frameErrorRateEntryCls);
            chip::JniClass frameErrorRateJniClass(frameErrorRateEntryCls);
            jmethodID frameErrorRateEntryTypeCtor = env->GetMethodID(frameErrorRateEntryCls, "<init>", "(I)V");
            frameErrorRate = env->NewObject(frameErrorRateEntryCls, frameErrorRateEntryTypeCtor, frameErrorRateValue);
        }

        bool messageErrorRateNull     = false;
        bool messageErrorRateHasValue = true;

        uint8_t messageErrorRateValue = entry.messageErrorRate;

        jobject messageErrorRate = nullptr;
        if (!messageErrorRateNull && messageErrorRateHasValue)
        {
            jclass messageErrorRateEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", messageErrorRateEntryCls);
            chip::JniClass messageErrorRateJniClass(messageErrorRateEntryCls);
            jmethodID messageErrorRateEntryTypeCtor = env->GetMethodID(messageErrorRateEntryCls, "<init>", "(I)V");
            messageErrorRate = env->NewObject(messageErrorRateEntryCls, messageErrorRateEntryTypeCtor, messageErrorRateValue);
        }

        bool rxOnWhenIdleNull     = false;
        bool rxOnWhenIdleHasValue = true;

        bool rxOnWhenIdleValue = entry.rxOnWhenIdle;

        jobject rxOnWhenIdle = nullptr;
        if (!rxOnWhenIdleNull && rxOnWhenIdleHasValue)
        {
            jclass rxOnWhenIdleEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", rxOnWhenIdleEntryCls);
            chip::JniClass rxOnWhenIdleJniClass(rxOnWhenIdleEntryCls);
            jmethodID rxOnWhenIdleEntryTypeCtor = env->GetMethodID(rxOnWhenIdleEntryCls, "<init>", "(Z)V");
            rxOnWhenIdle = env->NewObject(rxOnWhenIdleEntryCls, rxOnWhenIdleEntryTypeCtor, rxOnWhenIdleValue);
        }

        bool fullThreadDeviceNull     = false;
        bool fullThreadDeviceHasValue = true;

        bool fullThreadDeviceValue = entry.fullThreadDevice;

        jobject fullThreadDevice = nullptr;
        if (!fullThreadDeviceNull && fullThreadDeviceHasValue)
        {
            jclass fullThreadDeviceEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", fullThreadDeviceEntryCls);
            chip::JniClass fullThreadDeviceJniClass(fullThreadDeviceEntryCls);
            jmethodID fullThreadDeviceEntryTypeCtor = env->GetMethodID(fullThreadDeviceEntryCls, "<init>", "(Z)V");
            fullThreadDevice = env->NewObject(fullThreadDeviceEntryCls, fullThreadDeviceEntryTypeCtor, fullThreadDeviceValue);
        }

        bool fullNetworkDataNull     = false;
        bool fullNetworkDataHasValue = true;

        bool fullNetworkDataValue = entry.fullNetworkData;

        jobject fullNetworkData = nullptr;
        if (!fullNetworkDataNull && fullNetworkDataHasValue)
        {
            jclass fullNetworkDataEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", fullNetworkDataEntryCls);
            chip::JniClass fullNetworkDataJniClass(fullNetworkDataEntryCls);
            jmethodID fullNetworkDataEntryTypeCtor = env->GetMethodID(fullNetworkDataEntryCls, "<init>", "(Z)V");
            fullNetworkData = env->NewObject(fullNetworkDataEntryCls, fullNetworkDataEntryTypeCtor, fullNetworkDataValue);
        }

        bool isChildNull     = false;
        bool isChildHasValue = true;

        bool isChildValue = entry.isChild;

        jobject isChild = nullptr;
        if (!isChildNull && isChildHasValue)
        {
            jclass isChildEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", isChildEntryCls);
            chip::JniClass isChildJniClass(isChildEntryCls);
            jmethodID isChildEntryTypeCtor = env->GetMethodID(isChildEntryCls, "<init>", "(Z)V");
            isChild                        = env->NewObject(isChildEntryCls, isChildEntryTypeCtor, isChildValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, extAddress, age, rloc16, linkFrameCounter,
                                              mleFrameCounter, lqi, averageRssi, lastRssi, frameErrorRate, messageErrorRate,
                                              rxOnWhenIdle, fullThreadDevice, fullNetworkData, isChild);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create NeighborTableListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding NeighborTableListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback::CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterRouteTableListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback::~CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::ThreadNetworkDiagnostics::Structs::RouteTable::DecodableType> &
        list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsRouteTableListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$RouteTableListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl,
            "Could not find class chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$RouteTableListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor =
        env->GetMethodID(attributeClass, "<init>",
                         "(Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/"
                         "Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find RouteTableListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool extAddressNull     = false;
        bool extAddressHasValue = true;

        uint64_t extAddressValue = entry.extAddress;

        jobject extAddress = nullptr;
        if (!extAddressNull && extAddressHasValue)
        {
            jclass extAddressEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", extAddressEntryCls);
            chip::JniClass extAddressJniClass(extAddressEntryCls);
            jmethodID extAddressEntryTypeCtor = env->GetMethodID(extAddressEntryCls, "<init>", "(J)V");
            extAddress                        = env->NewObject(extAddressEntryCls, extAddressEntryTypeCtor, extAddressValue);
        }

        bool rloc16Null     = false;
        bool rloc16HasValue = true;

        uint16_t rloc16Value = entry.rloc16;

        jobject rloc16 = nullptr;
        if (!rloc16Null && rloc16HasValue)
        {
            jclass rloc16EntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", rloc16EntryCls);
            chip::JniClass rloc16JniClass(rloc16EntryCls);
            jmethodID rloc16EntryTypeCtor = env->GetMethodID(rloc16EntryCls, "<init>", "(I)V");
            rloc16                        = env->NewObject(rloc16EntryCls, rloc16EntryTypeCtor, rloc16Value);
        }

        bool routerIdNull     = false;
        bool routerIdHasValue = true;

        uint8_t routerIdValue = entry.routerId;

        jobject routerId = nullptr;
        if (!routerIdNull && routerIdHasValue)
        {
            jclass routerIdEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", routerIdEntryCls);
            chip::JniClass routerIdJniClass(routerIdEntryCls);
            jmethodID routerIdEntryTypeCtor = env->GetMethodID(routerIdEntryCls, "<init>", "(I)V");
            routerId                        = env->NewObject(routerIdEntryCls, routerIdEntryTypeCtor, routerIdValue);
        }

        bool nextHopNull     = false;
        bool nextHopHasValue = true;

        uint8_t nextHopValue = entry.nextHop;

        jobject nextHop = nullptr;
        if (!nextHopNull && nextHopHasValue)
        {
            jclass nextHopEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", nextHopEntryCls);
            chip::JniClass nextHopJniClass(nextHopEntryCls);
            jmethodID nextHopEntryTypeCtor = env->GetMethodID(nextHopEntryCls, "<init>", "(I)V");
            nextHop                        = env->NewObject(nextHopEntryCls, nextHopEntryTypeCtor, nextHopValue);
        }

        bool pathCostNull     = false;
        bool pathCostHasValue = true;

        uint8_t pathCostValue = entry.pathCost;

        jobject pathCost = nullptr;
        if (!pathCostNull && pathCostHasValue)
        {
            jclass pathCostEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", pathCostEntryCls);
            chip::JniClass pathCostJniClass(pathCostEntryCls);
            jmethodID pathCostEntryTypeCtor = env->GetMethodID(pathCostEntryCls, "<init>", "(I)V");
            pathCost                        = env->NewObject(pathCostEntryCls, pathCostEntryTypeCtor, pathCostValue);
        }

        bool LQIInNull     = false;
        bool LQIInHasValue = true;

        uint8_t LQIInValue = entry.LQIIn;

        jobject LQIIn = nullptr;
        if (!LQIInNull && LQIInHasValue)
        {
            jclass LQIInEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", LQIInEntryCls);
            chip::JniClass LQIInJniClass(LQIInEntryCls);
            jmethodID LQIInEntryTypeCtor = env->GetMethodID(LQIInEntryCls, "<init>", "(I)V");
            LQIIn                        = env->NewObject(LQIInEntryCls, LQIInEntryTypeCtor, LQIInValue);
        }

        bool LQIOutNull     = false;
        bool LQIOutHasValue = true;

        uint8_t LQIOutValue = entry.LQIOut;

        jobject LQIOut = nullptr;
        if (!LQIOutNull && LQIOutHasValue)
        {
            jclass LQIOutEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", LQIOutEntryCls);
            chip::JniClass LQIOutJniClass(LQIOutEntryCls);
            jmethodID LQIOutEntryTypeCtor = env->GetMethodID(LQIOutEntryCls, "<init>", "(I)V");
            LQIOut                        = env->NewObject(LQIOutEntryCls, LQIOutEntryTypeCtor, LQIOutValue);
        }

        bool ageNull     = false;
        bool ageHasValue = true;

        uint8_t ageValue = entry.age;

        jobject age = nullptr;
        if (!ageNull && ageHasValue)
        {
            jclass ageEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", ageEntryCls);
            chip::JniClass ageJniClass(ageEntryCls);
            jmethodID ageEntryTypeCtor = env->GetMethodID(ageEntryCls, "<init>", "(I)V");
            age                        = env->NewObject(ageEntryCls, ageEntryTypeCtor, ageValue);
        }

        bool allocatedNull     = false;
        bool allocatedHasValue = true;

        bool allocatedValue = entry.allocated;

        jobject allocated = nullptr;
        if (!allocatedNull && allocatedHasValue)
        {
            jclass allocatedEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", allocatedEntryCls);
            chip::JniClass allocatedJniClass(allocatedEntryCls);
            jmethodID allocatedEntryTypeCtor = env->GetMethodID(allocatedEntryCls, "<init>", "(Z)V");
            allocated                        = env->NewObject(allocatedEntryCls, allocatedEntryTypeCtor, allocatedValue);
        }

        bool linkEstablishedNull     = false;
        bool linkEstablishedHasValue = true;

        bool linkEstablishedValue = entry.linkEstablished;

        jobject linkEstablished = nullptr;
        if (!linkEstablishedNull && linkEstablishedHasValue)
        {
            jclass linkEstablishedEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", linkEstablishedEntryCls);
            chip::JniClass linkEstablishedJniClass(linkEstablishedEntryCls);
            jmethodID linkEstablishedEntryTypeCtor = env->GetMethodID(linkEstablishedEntryCls, "<init>", "(Z)V");
            linkEstablished = env->NewObject(linkEstablishedEntryCls, linkEstablishedEntryTypeCtor, linkEstablishedValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, extAddress, rloc16, routerId, nextHop, pathCost, LQIIn,
                                              LQIOut, age, allocated, linkEstablished);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create RouteTableListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding RouteTableListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback::CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterSecurityPolicyAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback::~CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::ThreadNetworkDiagnostics::Structs::SecurityPolicy::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsSecurityPolicyAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$SecurityPolicyAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(
            Zcl,
            "Could not find class chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$SecurityPolicyAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/Integer;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find SecurityPolicyAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool rotationTimeNull     = false;
        bool rotationTimeHasValue = true;

        uint16_t rotationTimeValue = entry.rotationTime;

        jobject rotationTime = nullptr;
        if (!rotationTimeNull && rotationTimeHasValue)
        {
            jclass rotationTimeEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", rotationTimeEntryCls);
            chip::JniClass rotationTimeJniClass(rotationTimeEntryCls);
            jmethodID rotationTimeEntryTypeCtor = env->GetMethodID(rotationTimeEntryCls, "<init>", "(I)V");
            rotationTime = env->NewObject(rotationTimeEntryCls, rotationTimeEntryTypeCtor, rotationTimeValue);
        }

        bool flagsNull     = false;
        bool flagsHasValue = true;

        uint16_t flagsValue = entry.flags;

        jobject flags = nullptr;
        if (!flagsNull && flagsHasValue)
        {
            jclass flagsEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", flagsEntryCls);
            chip::JniClass flagsJniClass(flagsEntryCls);
            jmethodID flagsEntryTypeCtor = env->GetMethodID(flagsEntryCls, "<init>", "(I)V");
            flags                        = env->NewObject(flagsEntryCls, flagsEntryTypeCtor, flagsValue);
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, rotationTime, flags);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create SecurityPolicyAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding SecurityPolicyAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback::
    CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterOperationalDatasetComponentsAttributeCallbackType>(CallbackFn,
                                                                                                                   this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback::
    ~CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<
        chip::app::Clusters::ThreadNetworkDiagnostics::Structs::OperationalDatasetComponents::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsOperationalDatasetComponentsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$OperationalDatasetComponentsAttribute",
        attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl,
                     "Could not find class "
                     "chip/devicecontroller/ChipClusters$ThreadNetworkDiagnosticsCluster$OperationalDatasetComponentsAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(
        attributeClass, "<init>",
        "(Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/"
        "lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find OperationalDatasetComponentsAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool activeTimestampPresentNull     = false;
        bool activeTimestampPresentHasValue = true;

        bool activeTimestampPresentValue = entry.activeTimestampPresent;

        jobject activeTimestampPresent = nullptr;
        if (!activeTimestampPresentNull && activeTimestampPresentHasValue)
        {
            jclass activeTimestampPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", activeTimestampPresentEntryCls);
            chip::JniClass activeTimestampPresentJniClass(activeTimestampPresentEntryCls);
            jmethodID activeTimestampPresentEntryTypeCtor = env->GetMethodID(activeTimestampPresentEntryCls, "<init>", "(Z)V");
            activeTimestampPresent =
                env->NewObject(activeTimestampPresentEntryCls, activeTimestampPresentEntryTypeCtor, activeTimestampPresentValue);
        }

        bool pendingTimestampPresentNull     = false;
        bool pendingTimestampPresentHasValue = true;

        bool pendingTimestampPresentValue = entry.pendingTimestampPresent;

        jobject pendingTimestampPresent = nullptr;
        if (!pendingTimestampPresentNull && pendingTimestampPresentHasValue)
        {
            jclass pendingTimestampPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", pendingTimestampPresentEntryCls);
            chip::JniClass pendingTimestampPresentJniClass(pendingTimestampPresentEntryCls);
            jmethodID pendingTimestampPresentEntryTypeCtor = env->GetMethodID(pendingTimestampPresentEntryCls, "<init>", "(Z)V");
            pendingTimestampPresent =
                env->NewObject(pendingTimestampPresentEntryCls, pendingTimestampPresentEntryTypeCtor, pendingTimestampPresentValue);
        }

        bool masterKeyPresentNull     = false;
        bool masterKeyPresentHasValue = true;

        bool masterKeyPresentValue = entry.masterKeyPresent;

        jobject masterKeyPresent = nullptr;
        if (!masterKeyPresentNull && masterKeyPresentHasValue)
        {
            jclass masterKeyPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", masterKeyPresentEntryCls);
            chip::JniClass masterKeyPresentJniClass(masterKeyPresentEntryCls);
            jmethodID masterKeyPresentEntryTypeCtor = env->GetMethodID(masterKeyPresentEntryCls, "<init>", "(Z)V");
            masterKeyPresent = env->NewObject(masterKeyPresentEntryCls, masterKeyPresentEntryTypeCtor, masterKeyPresentValue);
        }

        bool networkNamePresentNull     = false;
        bool networkNamePresentHasValue = true;

        bool networkNamePresentValue = entry.networkNamePresent;

        jobject networkNamePresent = nullptr;
        if (!networkNamePresentNull && networkNamePresentHasValue)
        {
            jclass networkNamePresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", networkNamePresentEntryCls);
            chip::JniClass networkNamePresentJniClass(networkNamePresentEntryCls);
            jmethodID networkNamePresentEntryTypeCtor = env->GetMethodID(networkNamePresentEntryCls, "<init>", "(Z)V");
            networkNamePresent =
                env->NewObject(networkNamePresentEntryCls, networkNamePresentEntryTypeCtor, networkNamePresentValue);
        }

        bool extendedPanIdPresentNull     = false;
        bool extendedPanIdPresentHasValue = true;

        bool extendedPanIdPresentValue = entry.extendedPanIdPresent;

        jobject extendedPanIdPresent = nullptr;
        if (!extendedPanIdPresentNull && extendedPanIdPresentHasValue)
        {
            jclass extendedPanIdPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", extendedPanIdPresentEntryCls);
            chip::JniClass extendedPanIdPresentJniClass(extendedPanIdPresentEntryCls);
            jmethodID extendedPanIdPresentEntryTypeCtor = env->GetMethodID(extendedPanIdPresentEntryCls, "<init>", "(Z)V");
            extendedPanIdPresent =
                env->NewObject(extendedPanIdPresentEntryCls, extendedPanIdPresentEntryTypeCtor, extendedPanIdPresentValue);
        }

        bool meshLocalPrefixPresentNull     = false;
        bool meshLocalPrefixPresentHasValue = true;

        bool meshLocalPrefixPresentValue = entry.meshLocalPrefixPresent;

        jobject meshLocalPrefixPresent = nullptr;
        if (!meshLocalPrefixPresentNull && meshLocalPrefixPresentHasValue)
        {
            jclass meshLocalPrefixPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", meshLocalPrefixPresentEntryCls);
            chip::JniClass meshLocalPrefixPresentJniClass(meshLocalPrefixPresentEntryCls);
            jmethodID meshLocalPrefixPresentEntryTypeCtor = env->GetMethodID(meshLocalPrefixPresentEntryCls, "<init>", "(Z)V");
            meshLocalPrefixPresent =
                env->NewObject(meshLocalPrefixPresentEntryCls, meshLocalPrefixPresentEntryTypeCtor, meshLocalPrefixPresentValue);
        }

        bool delayPresentNull     = false;
        bool delayPresentHasValue = true;

        bool delayPresentValue = entry.delayPresent;

        jobject delayPresent = nullptr;
        if (!delayPresentNull && delayPresentHasValue)
        {
            jclass delayPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", delayPresentEntryCls);
            chip::JniClass delayPresentJniClass(delayPresentEntryCls);
            jmethodID delayPresentEntryTypeCtor = env->GetMethodID(delayPresentEntryCls, "<init>", "(Z)V");
            delayPresent = env->NewObject(delayPresentEntryCls, delayPresentEntryTypeCtor, delayPresentValue);
        }

        bool panIdPresentNull     = false;
        bool panIdPresentHasValue = true;

        bool panIdPresentValue = entry.panIdPresent;

        jobject panIdPresent = nullptr;
        if (!panIdPresentNull && panIdPresentHasValue)
        {
            jclass panIdPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", panIdPresentEntryCls);
            chip::JniClass panIdPresentJniClass(panIdPresentEntryCls);
            jmethodID panIdPresentEntryTypeCtor = env->GetMethodID(panIdPresentEntryCls, "<init>", "(Z)V");
            panIdPresent = env->NewObject(panIdPresentEntryCls, panIdPresentEntryTypeCtor, panIdPresentValue);
        }

        bool channelPresentNull     = false;
        bool channelPresentHasValue = true;

        bool channelPresentValue = entry.channelPresent;

        jobject channelPresent = nullptr;
        if (!channelPresentNull && channelPresentHasValue)
        {
            jclass channelPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", channelPresentEntryCls);
            chip::JniClass channelPresentJniClass(channelPresentEntryCls);
            jmethodID channelPresentEntryTypeCtor = env->GetMethodID(channelPresentEntryCls, "<init>", "(Z)V");
            channelPresent = env->NewObject(channelPresentEntryCls, channelPresentEntryTypeCtor, channelPresentValue);
        }

        bool pskcPresentNull     = false;
        bool pskcPresentHasValue = true;

        bool pskcPresentValue = entry.pskcPresent;

        jobject pskcPresent = nullptr;
        if (!pskcPresentNull && pskcPresentHasValue)
        {
            jclass pskcPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", pskcPresentEntryCls);
            chip::JniClass pskcPresentJniClass(pskcPresentEntryCls);
            jmethodID pskcPresentEntryTypeCtor = env->GetMethodID(pskcPresentEntryCls, "<init>", "(Z)V");
            pskcPresent                        = env->NewObject(pskcPresentEntryCls, pskcPresentEntryTypeCtor, pskcPresentValue);
        }

        bool securityPolicyPresentNull     = false;
        bool securityPolicyPresentHasValue = true;

        bool securityPolicyPresentValue = entry.securityPolicyPresent;

        jobject securityPolicyPresent = nullptr;
        if (!securityPolicyPresentNull && securityPolicyPresentHasValue)
        {
            jclass securityPolicyPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", securityPolicyPresentEntryCls);
            chip::JniClass securityPolicyPresentJniClass(securityPolicyPresentEntryCls);
            jmethodID securityPolicyPresentEntryTypeCtor = env->GetMethodID(securityPolicyPresentEntryCls, "<init>", "(Z)V");
            securityPolicyPresent =
                env->NewObject(securityPolicyPresentEntryCls, securityPolicyPresentEntryTypeCtor, securityPolicyPresentValue);
        }

        bool channelMaskPresentNull     = false;
        bool channelMaskPresentHasValue = true;

        bool channelMaskPresentValue = entry.channelMaskPresent;

        jobject channelMaskPresent = nullptr;
        if (!channelMaskPresentNull && channelMaskPresentHasValue)
        {
            jclass channelMaskPresentEntryCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Boolean", channelMaskPresentEntryCls);
            chip::JniClass channelMaskPresentJniClass(channelMaskPresentEntryCls);
            jmethodID channelMaskPresentEntryTypeCtor = env->GetMethodID(channelMaskPresentEntryCls, "<init>", "(Z)V");
            channelMaskPresent =
                env->NewObject(channelMaskPresentEntryCls, channelMaskPresentEntryTypeCtor, channelMaskPresentValue);
        }

        jobject attributeObj =
            env->NewObject(attributeClass, attributeCtor, activeTimestampPresent, pendingTimestampPresent, masterKeyPresent,
                           networkNamePresent, extendedPanIdPresent, meshLocalPrefixPresent, delayPresent, panIdPresent,
                           channelPresent, pskcPresent, securityPolicyPresent, channelMaskPresent);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create OperationalDatasetComponentsAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding OperationalDatasetComponentsAttribute value: %" CHIP_ERROR_FORMAT,
                                iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback::
    CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterActiveNetworkFaultsListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback::
    ~CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::app::Clusters::ThreadNetworkDiagnostics::NetworkFault> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsActiveNetworkFaultsListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                                                           = iter.GetValue();
        bool entryNull                                                         = false;
        chip::app::Clusters::ThreadNetworkDiagnostics::NetworkFault entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Integer", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(I)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding ActiveNetworkFaultsListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback::CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPThreadNetworkDiagnosticsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback::~CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPThreadNetworkDiagnosticsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPUserLabelLabelListAttributeCallback::CHIPUserLabelLabelListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPUserLabelClusterLabelListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPUserLabelLabelListAttributeCallback::~CHIPUserLabelLabelListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPUserLabelLabelListAttributeCallback::CallbackFn(
    void * context,
    const chip::app::DataModel::DecodableList<chip::app::Clusters::UserLabel::Structs::LabelStruct::DecodableType> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPUserLabelLabelListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPUserLabelLabelListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jclass attributeClass;
    err = chip::JniReferences::GetInstance().GetClassRef(
        env, "chip/devicecontroller/ChipClusters$UserLabelCluster$LabelListAttribute", attributeClass);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Could not find class chip/devicecontroller/ChipClusters$UserLabelCluster$LabelListAttribute"));
    chip::JniClass attributeJniClass(attributeClass);
    jmethodID attributeCtor = env->GetMethodID(attributeClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
    VerifyOrReturn(attributeCtor != nullptr, ChipLogError(Zcl, "Could not find LabelListAttribute constructor"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry = iter.GetValue();
        (void) entry;
        bool labelNull     = false;
        bool labelHasValue = true;

        chip::CharSpan labelValue = entry.label;

        jstring label = nullptr;
        chip::UtfString labelStr(env, labelValue);
        if (!labelNull && labelHasValue)
        {
            label = jstring(labelStr.jniValue());
        }

        bool valueNull     = false;
        bool valueHasValue = true;

        chip::CharSpan valueValue = entry.value;

        jstring value = nullptr;
        chip::UtfString valueStr(env, valueValue);
        if (!valueNull && valueHasValue)
        {
            value = jstring(valueStr.jniValue());
        }

        jobject attributeObj = env->NewObject(attributeClass, attributeCtor, label, value);
        VerifyOrReturn(attributeObj != nullptr, ChipLogError(Zcl, "Could not create LabelListAttribute object"));

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, attributeObj);
    }
    VerifyOrReturn(iter.GetStatus() == CHIP_NO_ERROR,
                   ChipLogError(Zcl, "Error decoding LabelListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPWakeOnLanAttributeListAttributeCallback::CHIPWakeOnLanAttributeListAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWakeOnLanClusterAttributeListAttributeCallbackType>(CallbackFn, this), keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWakeOnLanAttributeListAttributeCallback::~CHIPWakeOnLanAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWakeOnLanAttributeListAttributeCallback::CallbackFn(void * context,
                                                             const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPWakeOnLanAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWakeOnLanAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback::CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWiFiNetworkDiagnosticsClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback::~CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWiFiNetworkDiagnosticsAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}

CHIPWindowCoveringCurrentPositionLiftAttributeCallback::CHIPWindowCoveringCurrentPositionLiftAttributeCallback(jobject javaCallback,
                                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionLiftAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionLiftAttributeCallback::~CHIPWindowCoveringCurrentPositionLiftAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionLiftAttributeCallback::CallbackFn(void * context,
                                                                        const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionLiftAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionLiftAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringCurrentPositionTiltAttributeCallback::CHIPWindowCoveringCurrentPositionTiltAttributeCallback(jobject javaCallback,
                                                                                                               bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionTiltAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionTiltAttributeCallback::~CHIPWindowCoveringCurrentPositionTiltAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionTiltAttributeCallback::CallbackFn(void * context,
                                                                        const chip::app::DataModel::Nullable<uint16_t> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionTiltAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionTiltAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<uint16_t>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                   value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback::CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionLiftPercentageAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback::
    ~CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionLiftPercentageAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                        value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback::CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback(
    jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionTiltPercentageAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback::
    ~CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionTiltPercentageAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent>(javaValueClassName.c_str(), javaValueCtorSignature.c_str(),
                                                                        value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback::
    CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterTargetPositionLiftPercent100thsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback::
    ~CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent100ths> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringTargetPositionLiftPercent100thsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent100ths>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback::
    CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterTargetPositionTiltPercent100thsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback::
    ~CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent100ths> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringTargetPositionTiltPercent100thsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent100ths>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback::
    CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionLiftPercent100thsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback::
    ~CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent100ths> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionLiftPercent100thsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent100ths>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback::
    CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback(jobject javaCallback, bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterCurrentPositionTiltPercent100thsAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback::
    ~CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::Nullable<chip::Percent100ths> & value)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));
    std::unique_ptr<CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringCurrentPositionTiltPercent100thsAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/lang/Integer;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    jobject javaValue;

    std::string javaValueClassName     = "java/lang/Integer";
    std::string javaValueCtorSignature = "(I)V";
    chip::JniReferences::GetInstance().CreateBoxedObject<chip::Percent100ths>(
        javaValueClassName.c_str(), javaValueCtorSignature.c_str(), value.Value(), javaValue);

    env->CallVoidMethod(javaCallbackRef, javaMethod, javaValue);
}

CHIPWindowCoveringAttributeListAttributeCallback::CHIPWindowCoveringAttributeListAttributeCallback(jobject javaCallback,
                                                                                                   bool keepAlive) :
    chip::Callback::Callback<CHIPWindowCoveringClusterAttributeListAttributeCallbackType>(CallbackFn, this),
    keepAlive(keepAlive)
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
        return;
    }

    javaCallbackRef = env->NewGlobalRef(javaCallback);
    if (javaCallbackRef == nullptr)
    {
        ChipLogError(Zcl, "Could not create global reference for Java callback");
    }
}

CHIPWindowCoveringAttributeListAttributeCallback::~CHIPWindowCoveringAttributeListAttributeCallback()
{
    JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    if (env == nullptr)
    {
        ChipLogError(Zcl, "Could not delete global reference for Java callback");
        return;
    }
    env->DeleteGlobalRef(javaCallbackRef);
}

void CHIPWindowCoveringAttributeListAttributeCallback::CallbackFn(
    void * context, const chip::app::DataModel::DecodableList<chip::AttributeId> & list)
{
    chip::DeviceLayer::StackUnlock unlock;
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
    jobject javaCallbackRef;

    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNI env"));

    std::unique_ptr<CHIPWindowCoveringAttributeListAttributeCallback, decltype(&maybeDestroy)> cppCallback(
        reinterpret_cast<CHIPWindowCoveringAttributeListAttributeCallback *>(context), maybeDestroy);

    // It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
    javaCallbackRef = cppCallback.get()->javaCallbackRef;
    VerifyOrReturn(javaCallbackRef != nullptr,
                   ChipLogProgress(Zcl, "Early return from attribute callback since Java callback is null"));

    jclass arrayListClass;
    err = chip::JniReferences::GetInstance().GetClassRef(env, "java/util/ArrayList", arrayListClass);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error using Java ArrayList"));
    chip::JniClass arrayListJniClass(arrayListClass);
    jmethodID arrayListCtor      = env->GetMethodID(arrayListClass, "<init>", "()V");
    jmethodID arrayListAddMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    VerifyOrReturn(arrayListCtor != nullptr && arrayListAddMethod != nullptr,
                   ChipLogError(Zcl, "Error finding Java ArrayList methods"));
    jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
    VerifyOrReturn(arrayListObj != nullptr, ChipLogError(Zcl, "Error creating Java ArrayList"));

    jmethodID javaMethod;
    err = chip::JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "(Ljava/util/List;)V", &javaMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Could not find onSuccess() method"));

    auto iter = list.begin();
    while (iter.Next())
    {
        auto & entry                 = iter.GetValue();
        bool entryNull               = false;
        chip::AttributeId entryValue = entry;

        jobject entryObject = nullptr;
        if (!entryNull)
        {
            jclass entryTypeCls;
            chip::JniReferences::GetInstance().GetClassRef(env, "java/lang/Long", entryTypeCls);
            chip::JniClass jniClass(entryTypeCls);
            jmethodID entryTypeCtor = env->GetMethodID(entryTypeCls, "<init>", "(J)V");
            entryObject             = env->NewObject(entryTypeCls, entryTypeCtor, entryValue);
        }

        env->CallBooleanMethod(arrayListObj, arrayListAddMethod, entryObject);
    }
    VerifyOrReturn(
        iter.GetStatus() == CHIP_NO_ERROR,
        ChipLogError(Zcl, "Error decoding AttributeListAttribute value: %" CHIP_ERROR_FORMAT, iter.GetStatus().Format()));

    env->ExceptionClear();
    env->CallVoidMethod(javaCallbackRef, javaMethod, arrayListObj);
}
